From 4eb91dc4a8901400af9fccc9af21a359ac56b9ac Mon Sep 17 00:00:00 2001 From: jfeinstein10 Date: Wed, 4 Jul 2012 10:13:24 -0700 Subject: [PATCH] SlidingFragmentActivity works. Getting a null pointer with SlidingListActivity. Don't know what's up there... --- .metadata/.lock | 0 .metadata/.log | 3057 +++++++++++++++++ .metadata/.log-ajde | 5 + .../TabHost.png | Bin 0 -> 254 bytes .../TabWidget.png | Bin 0 -> 141 bytes .../preview.properties | 2 + .../AnalogClock.png | Bin 0 -> 2193 bytes .../AutoCompleteTextView.png | Bin 0 -> 2315 bytes .../Button.png | Bin 0 -> 1232 bytes .../CalendarView.png | Bin 0 -> 13214 bytes .../CheckBox.png | Bin 0 -> 3592 bytes .../CheckedTextView.png | Bin 0 -> 2330 bytes .../Date.png | Bin 0 -> 1288 bytes .../DigitalClock.png | Bin 0 -> 1558 bytes .../Email.png | Bin 0 -> 2831 bytes .../ExpandableListView.png | Bin 0 -> 4192 bytes .../ImageButton.png | Bin 0 -> 881 bytes .../ImageView.png | Bin 0 -> 603 bytes .../LargeText.png | Bin 0 -> 1376 bytes .../ListView.png | Bin 0 -> 3265 bytes .../MediumText.png | Bin 0 -> 1321 bytes .../MultiAutoCompleteTextView.png | Bin 0 -> 2687 bytes .../MultilineText.png | Bin 0 -> 8432 bytes .../Number.png | Bin 0 -> 838 bytes .../NumberDecimal.png | Bin 0 -> 1151 bytes .../NumberSigned.png | Bin 0 -> 844 bytes .../Password.png | Bin 0 -> 349 bytes .../PasswordNumeric.png | Bin 0 -> 1171 bytes .../PersonName.png | Bin 0 -> 1911 bytes .../Phone.png | Bin 0 -> 1806 bytes .../PlainText.png | Bin 0 -> 1136 bytes .../PostalAddress.png | Bin 0 -> 1971 bytes .../ProgressBarHorizontal.png | Bin 0 -> 929 bytes .../ProgressBarLarge.png | Bin 0 -> 3845 bytes .../ProgressBarNormal.png | Bin 0 -> 2474 bytes .../ProgressBarSmall.png | Bin 0 -> 732 bytes .../QuickContactBadge.png | Bin 0 -> 2888 bytes .../RadioButton.png | Bin 0 -> 2879 bytes .../RadioGroup.png | Bin 0 -> 1874 bytes .../RatingBar.png | Bin 0 -> 3870 bytes .../SeekBar.png | Bin 0 -> 1973 bytes .../SmallButton.png | Bin 0 -> 1026 bytes .../SmallText.png | Bin 0 -> 806 bytes .../Spinner.png | Bin 0 -> 1267 bytes .../Switch.png | Bin 0 -> 724 bytes .../TabHost.png | Bin 0 -> 2116 bytes .../TabWidget.png | Bin 0 -> 880 bytes .../TextView.png | Bin 0 -> 1138 bytes .../Time.png | Bin 0 -> 1559 bytes .../ToggleButton.png | Bin 0 -> 668 bytes .../ZoomButton.png | Bin 0 -> 4601 bytes .../ZoomControls.png | Bin 0 -> 4686 bytes .../preview.properties | 2 + .../0/4064100f09c3001119baa706e9d70c26 | 778 +++++ .../0/60866c2216c3001119baa706e9d70c26 | 1154 +++++++ .../0/a05891ff24c3001119baa706e9d70c26 | Bin 0 -> 83 bytes .../1/124c97ff24c3001119baa706e9d70c26 | 134 + .../1/408c8bff24c3001119baa706e9d70c26 | Bin 0 -> 148 bytes .../1/43fd8dff24c3001119baa706e9d70c26 | Bin 0 -> 131 bytes .../1/91a293ff24c3001119baa706e9d70c26 | 380 ++ .../10/0060e76d24c500111b2a8b7f47e59881 | 0 .../10/10660e4d1ec3001119baa706e9d70c26 | 778 +++++ .../10/800a91ff24c3001119baa706e9d70c26 | Bin 0 -> 915 bytes .../11/308173515bc300111ab8b17b137f3789 | 143 + .../11/600d2b0d54c3001115d2d454e05194c5 | 5 + .../11/90cb999352c3001119baa706e9d70c26 | 19 + .../11/c07980e02ac500111b2a8b7f47e59881 | 155 + .../11/e1128dff24c3001119baa706e9d70c26 | Bin 0 -> 2851 bytes .../12/9062a79e52c3001119baa706e9d70c26 | 21 + .../12/b1f093ff24c3001119baa706e9d70c26 | 226 ++ .../13/00abe03af4c500111689feaa37e8ab14 | 198 ++ .../13/01618dff24c3001119baa706e9d70c26 | Bin 0 -> 127 bytes .../13/50ab3dce27c500111b2a8b7f47e59881 | 32 + .../13/72e390ff24c3001119baa706e9d70c26 | Bin 0 -> 970 bytes .../14/02618dff24c3001119baa706e9d70c26 | Bin 0 -> 123 bytes .../14/11db94ff24c3001119baa706e9d70c26 | 45 + .../14/d0475e0416c3001119baa706e9d70c26 | 1158 +++++++ .../15/034392ff24c3001119baa706e9d70c26 | Bin 0 -> 602 bytes .../15/108247f025c3001119baa706e9d70c26 | 1182 +++++++ .../15/10e44a7c48c3001119baa706e9d70c26 | 218 ++ .../15/5049ccb55bc300111ab8b17b137f3789 | 139 + .../15/a35891ff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../15/f095f093f6c500111689feaa37e8ab14 | 7 + .../15/f0aa8fff24c3001119baa706e9d70c26 | Bin 0 -> 166 bytes .../16/106a92ff24c3001119baa706e9d70c26 | Bin 0 -> 153 bytes .../16/40b72d9993c500111b2a8b7f47e59881 | 196 ++ .../17/42df92ff24c3001119baa706e9d70c26 | 53 + .../17/a1e78eff24c3001119baa706e9d70c26 | Bin 0 -> 249 bytes .../17/b17f91ff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../17/c0ffac6d5bc300111ab8b17b137f3789 | 138 + .../17/d1af96ff24c3001119baa706e9d70c26 | 278 ++ .../17/f11b92ff24c3001119baa706e9d70c26 | Bin 0 -> 394 bytes .../17/f1fd96ff24c3001119baa706e9d70c26 | 647 ++++ .../18/53248eff24c3001119baa706e9d70c26 | Bin 0 -> 78 bytes .../18/b0e0d3895bc300111ab8b17b137f3789 | 138 + .../18/d0b0605522c3001119baa706e9d70c26 | 216 ++ .../1a/0080b4134dc3001119baa706e9d70c26 | 218 ++ .../1a/4007eefdf5c500111689feaa37e8ab14 | 12 + .../1a/d0092b01f6c500111689feaa37e8ab14 | 12 + .../1b/735493ff24c3001119baa706e9d70c26 | 40 + .../1b/d086255424c3001119baa706e9d70c26 | 216 ++ .../1c/305e0e93f4c500111689feaa37e8ab14 | 7 + .../1c/90be36fe0cc3001119baa706e9d70c26 | 779 +++++ .../1d/223e8bff24c3001119baa706e9d70c26 | Bin 0 -> 1537 bytes .../1d/51248eff24c3001119baa706e9d70c26 | Bin 0 -> 355 bytes .../1d/72018cff24c3001119baa706e9d70c26 | Bin 0 -> 174 bytes .../1e/319a97ff24c3001119baa706e9d70c26 | 518 +++ .../1e/70f3e032f8c500111689feaa37e8ab14 | 196 ++ .../1e/f0398dff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../1f/c0845dea21c3001119baa706e9d70c26 | 1026 ++++++ .../1f/e1d696ff24c3001119baa706e9d70c26 | 231 ++ .../2/10d077ea0cc3001119baa706e9d70c26 | 95 + .../2/20946fb921c3001119baa706e9d70c26 | 216 ++ .../2/8099fbcc26c3001119baa706e9d70c26 | 215 ++ .../20/02b494ff24c3001119baa706e9d70c26 | 22 + .../21/30341a1d1dc3001119baa706e9d70c26 | 216 ++ .../22/807e73955bc300111ab8b17b137f3789 | 138 + .../22/810a91ff24c3001119baa706e9d70c26 | Bin 0 -> 167 bytes .../22/a03a96ff24c3001119baa706e9d70c26 | 205 ++ .../22/e3f491ff24c3001119baa706e9d70c26 | Bin 0 -> 1007 bytes .../23/60ed698bf5c500111689feaa37e8ab14 | 10 + .../23/b49d8cff24c3001119baa706e9d70c26 | Bin 0 -> 153 bytes .../23/c0e555472ac3001119baa706e9d70c26 | 215 ++ .../23/f3398dff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../24/729089ff24c3001119baa706e9d70c26 | 25 + .../24/82b789ff24c3001119baa706e9d70c26 | 20 + .../24/c0df82c992c500111b2a8b7f47e59881 | 24 + .../24/e2a18aff24c3001119baa706e9d70c26 | Bin 0 -> 146 bytes .../24/f0f870e429c3001119baa706e9d70c26 | 216 ++ .../25/749089ff24c3001119baa706e9d70c26 | 18 + .../26/519590ff24c3001119baa706e9d70c26 | Bin 0 -> 166 bytes .../26/e048c3922ac3001119baa706e9d70c26 | 24 + .../27/01b494ff24c3001119baa706e9d70c26 | 29 + .../27/6033c5f323c500111b2a8b7f47e59881 | 37 + .../27/609ea3ecf9c500111689feaa37e8ab14 | 41 + .../28/31658bff24c3001119baa706e9d70c26 | Bin 0 -> 713 bytes .../28/70057c8e2ec3001119baa706e9d70c26 | 255 ++ .../28/911396ff24c3001119baa706e9d70c26 | 44 + .../28/b27f91ff24c3001119baa706e9d70c26 | Bin 0 -> 190 bytes .../28/f0f29cfff9c500111689feaa37e8ab14 | 196 ++ .../28/f3aa8fff24c3001119baa706e9d70c26 | Bin 0 -> 2875 bytes .../29/30090a0115c3001119baa706e9d70c26 | 1210 +++++++ .../29/616989ff24c3001119baa706e9d70c26 | 21 + .../29/905af89f29c500111b2a8b7f47e59881 | 211 ++ .../2a/418c8bff24c3001119baa706e9d70c26 | Bin 0 -> 467 bytes .../2a/8022e93b50c3001119baa706e9d70c26 | 26 + .../2a/a02e166910c3001119baa706e9d70c26 | 18 + .../2b/107967b493c500111b2a8b7f47e59881 | 197 ++ .../2b/309ba40953c3001119baa706e9d70c26 | 145 + .../2b/609e95ff24c3001119baa706e9d70c26 | 468 +++ .../2b/80de661d26c3001119baa706e9d70c26 | 771 +++++ .../2b/934f8cff24c3001119baa706e9d70c26 | Bin 0 -> 306 bytes .../2b/c04155c62ac500111b2a8b7f47e59881 | 154 + .../2b/d04376d3f8c500111689feaa37e8ab14 | 8 + .../2b/d08076ac92c500111b2a8b7f47e59881 | 37 + .../2b/e0ba844116c3001119baa706e9d70c26 | 1027 ++++++ .../2d/b2f093ff24c3001119baa706e9d70c26 | 33 + .../2e/2054ee332cc3001119baa706e9d70c26 | 24 + .../2e/c1538aff24c3001119baa706e9d70c26 | Bin 0 -> 144 bytes .../2f/10c93c565bc300111ab8b17b137f3789 | 136 + .../2f/8044d37d16c3001119baa706e9d70c26 | 1154 +++++++ .../2f/80ef8a9d25c3001119baa706e9d70c26 | 214 ++ .../3/404300032bc500111b2a8b7f47e59881 | 159 + .../3/43c197ff24c3001119baa706e9d70c26 | 1160 +++++++ .../3/70780f1425c3001119baa706e9d70c26 | 215 ++ .../3/70a23da324c3001119baa706e9d70c26 | 215 ++ .../30/53e897ff24c3001119baa706e9d70c26 | 21 + .../30/f1aa8fff24c3001119baa706e9d70c26 | Bin 0 -> 153 bytes .../31/1068dc514ec3001119baa706e9d70c26 | 38 + .../32/002597ff24c3001119baa706e9d70c26 | 292 ++ .../32/100aca332bc500111b2a8b7f47e59881 | 196 ++ .../32/200295ff24c3001119baa706e9d70c26 | 778 +++++ .../32/72c595ff24c3001119baa706e9d70c26 | 42 + .../32/e07423b75bc300111ab8b17b137f3789 | 138 + .../32/e16594ff24c3001119baa706e9d70c26 | 38 + .../32/f01b92ff24c3001119baa706e9d70c26 | Bin 0 -> 395 bytes .../32/f0fd96ff24c3001119baa706e9d70c26 | 1335 +++++++ .../33/74c595ff24c3001119baa706e9d70c26 | 42 + .../33/82998eff24c3001119baa706e9d70c26 | Bin 0 -> 572 bytes .../34/8050194127c500111b2a8b7f47e59881 | 18 + .../34/a0909ce4f9c500111689feaa37e8ab14 | 39 + .../34/f2c88aff24c3001119baa706e9d70c26 | Bin 0 -> 145 bytes .../35/20cb185852c3001119baa706e9d70c26 | 21 + .../35/302995ff24c3001119baa706e9d70c26 | 253 ++ .../35/31d68dff24c3001119baa706e9d70c26 | Bin 0 -> 582 bytes .../35/51e897ff24c3001119baa706e9d70c26 | 1193 +++++++ .../35/7041672c50c3001119baa706e9d70c26 | 26 + .../35/80e1c04311c3001119baa706e9d70c26 | 18 + .../36/b05c60f4f9c500111689feaa37e8ab14 | 41 + .../36/b0ac19ae25c3001119baa706e9d70c26 | 215 ++ .../36/d1cd91ff24c3001119baa706e9d70c26 | Bin 0 -> 172 bytes .../36/e0fab3fc27c3001119baa706e9d70c26 | 18 + .../37/00bd789329c500111b2a8b7f47e59881 | 210 ++ .../37/210295ff24c3001119baa706e9d70c26 | 947 +++++ .../37/30f5e4251fc3001119baa706e9d70c26 | 1146 ++++++ .../37/c0b4cd8144c3001119baa706e9d70c26 | 254 ++ .../37/c0b7cddb14c3001119baa706e9d70c26 | 778 +++++ .../39/405b522352c3001119baa706e9d70c26 | 260 ++ .../39/70c4716c0ac3001119baa706e9d70c26 | 348 ++ .../39/a2058aff24c3001119baa706e9d70c26 | 25 + .../39/c3358fff24c3001119baa706e9d70c26 | Bin 0 -> 157 bytes .../3a/20041b1c53c3001119baa706e9d70c26 | 5 + .../3a/31b892ff24c3001119baa706e9d70c26 | 50 + .../3a/504289ff24c3001119baa706e9d70c26 | 20 + .../3a/52b38bff24c3001119baa706e9d70c26 | Bin 0 -> 154 bytes .../3a/600f98ff24c3001119baa706e9d70c26 | 224 ++ .../3a/c057f0272ec3001119baa706e9d70c26 | 747 ++++ .../3b/c0a56ae184c2001119baa706e9d70c26 | 1917 +++++++++++ .../3b/f1398dff24c3001119baa706e9d70c26 | Bin 0 -> 168 bytes .../3c/322995ff24c3001119baa706e9d70c26 | 253 ++ .../3c/b0dc31fa4fc3001119baa706e9d70c26 | 29 + .../3d/40770b6e0ac3001119baa706e9d70c26 | 349 ++ .../3e/006a1cff14c3001119baa706e9d70c26 | 1210 +++++++ .../3e/1022dd1016c3001119baa706e9d70c26 | 1154 +++++++ .../3e/500693ff24c3001119baa706e9d70c26 | 28 + .../3e/700c792750c3001119baa706e9d70c26 | 29 + .../3f/20eabc0b93c500111b2a8b7f47e59881 | 37 + .../3f/40f359ee30c500111b2a8b7f47e59881 | 41 + .../3f/a0caf7e90cc3001119baa706e9d70c26 | 1029 ++++++ .../3f/b0be286bf4c500111689feaa37e8ab14 | 41 + .../4/503515422ac500111b2a8b7f47e59881 | 213 ++ .../4/b0eb29d9f8c500111689feaa37e8ab14 | 22 + .../40/506bf92f31c500111b2a8b7f47e59881 | 198 ++ .../40/506e84b029c3001119baa706e9d70c26 | 24 + .../40/71e390ff24c3001119baa706e9d70c26 | Bin 0 -> 661 bytes .../40/b03079d925c3001119baa706e9d70c26 | 215 ++ .../41/90537ff530c500111b2a8b7f47e59881 | 196 ++ .../42/34d68dff24c3001119baa706e9d70c26 | Bin 0 -> 438 bytes .../42/510693ff24c3001119baa706e9d70c26 | 59 + .../42/a3c993ff24c3001119baa706e9d70c26 | 26 + .../43/106cb88024c500111b2a8b7f47e59881 | 7 + .../43/222090ff24c3001119baa706e9d70c26 | Bin 0 -> 152 bytes .../43/706aa73126c500111b2a8b7f47e59881 | 0 .../43/83998eff24c3001119baa706e9d70c26 | Bin 0 -> 572 bytes .../43/901e4c3952c3001119baa706e9d70c26 | Bin 0 -> 1356 bytes .../43/d0c39f1928c500111b2a8b7f47e59881 | 35 + .../44/30b3a98848c3001119baa706e9d70c26 | 218 ++ .../44/70ea366f24c500111b2a8b7f47e59881 | 7 + .../44/804e638329c500111b2a8b7f47e59881 | 207 ++ .../44/80cb36334ec3001119baa706e9d70c26 | 7 + .../44/b0588f1a1fc3001119baa706e9d70c26 | 1146 ++++++ .../44/c06fc2145cc300111ab8b17b137f3789 | 139 + .../44/e0a5eacfa4c300111ab8b17b137f3789 | 291 ++ .../45/20b4917e27c500111b2a8b7f47e59881 | 19 + .../45/e0dd634f15c3001119baa706e9d70c26 | 255 ++ .../46/201b429ff3c500111689feaa37e8ab14 | 1185 +++++++ .../46/514289ff24c3001119baa706e9d70c26 | 21 + .../46/6020896ef7c500111689feaa37e8ab14 | 7 + .../46/80cdb0cc29c3001119baa706e9d70c26 | 1182 +++++++ .../46/a009563952c3001119baa706e9d70c26 | Bin 0 -> 1579 bytes .../46/d011a3300dc3001119baa706e9d70c26 | 255 ++ .../46/e00ee88e48c3001119baa706e9d70c26 | 20 + .../47/530693ff24c3001119baa706e9d70c26 | 60 + .../47/70e189435dc300111ab8b17b137f3789 | 1026 ++++++ .../47/b26196ff24c3001119baa706e9d70c26 | 40 + .../48/44c197ff24c3001119baa706e9d70c26 | 248 ++ .../48/d0174c80f7c500111689feaa37e8ab14 | 41 + .../49/00618dff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../49/304ca72952c3001119baa706e9d70c26 | 23 + .../49/50e897ff24c3001119baa706e9d70c26 | 644 ++++ .../49/6097013231c500111b2a8b7f47e59881 | 197 ++ .../49/80dcec090bc3001119baa706e9d70c26 | 23 + .../49/c00e33f230c500111b2a8b7f47e59881 | 196 ++ .../49/f0f4be3226c500111b2a8b7f47e59881 | 7 + .../4a/60fc8a4d5bc300111ab8b17b137f3789 | 143 + .../4b/504468fa23c500111b2a8b7f47e59881 | 205 ++ .../4b/606d4ce884c2001119baa706e9d70c26 | 1516 ++++++++ .../4b/a07587ab10c3001119baa706e9d70c26 | 18 + .../4c/619e95ff24c3001119baa706e9d70c26 | 278 ++ .../4c/620f98ff24c3001119baa706e9d70c26 | 39 + .../4c/70f65436f6c500111689feaa37e8ab14 | 198 ++ .../4d/12f98fff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../4d/201c87f327c500111b2a8b7f47e59881 | 32 + .../4d/34b892ff24c3001119baa706e9d70c26 | 24 + .../4d/50f3542352c3001119baa706e9d70c26 | 203 ++ .../4e/004e4e77f7c500111689feaa37e8ab14 | 196 ++ .../4e/506ad73d16c3001119baa706e9d70c26 | 1027 ++++++ .../4e/506d569e5bc300111ab8b17b137f3789 | 138 + .../4e/606989ff24c3001119baa706e9d70c26 | 26 + .../4e/71018cff24c3001119baa706e9d70c26 | Bin 0 -> 178 bytes .../4e/c070ce372ac500111b2a8b7f47e59881 | 1873 ++++++++++ .../5/6058c6e993c500111b2a8b7f47e59881 | 198 ++ .../5/90b142b93ec3001119baa706e9d70c26 | 21 + .../50/329a97ff24c3001119baa706e9d70c26 | 1548 +++++++++ .../50/608eddae95c500111b2a8b7f47e59881 | 41 + .../50/90c36dfe4dc3001119baa706e9d70c26 | 218 ++ .../50/b00e8fff24c3001119baa706e9d70c26 | Bin 0 -> 424 bytes .../51/00ff810724c500111b2a8b7f47e59881 | 207 ++ .../51/20a7fa5929c3001119baa706e9d70c26 | 24 + .../51/41df92ff24c3001119baa706e9d70c26 | 70 + .../51/91de89ff24c3001119baa706e9d70c26 | 29 + .../51/c0cc6f3315c3001119baa706e9d70c26 | 1170 +++++++ .../52/701959d429c3001119baa706e9d70c26 | 215 ++ .../52/b067091b40c3001119baa706e9d70c26 | 215 ++ .../53/004392ff24c3001119baa706e9d70c26 | Bin 0 -> 680 bytes .../53/22af8dff24c3001119baa706e9d70c26 | Bin 0 -> 127 bytes .../53/70acb12952c3001119baa706e9d70c26 | 19 + .../53/73018cff24c3001119baa706e9d70c26 | Bin 0 -> 917 bytes .../53/80ffd98a2ec3001119baa706e9d70c26 | 255 ++ .../53/c21794ff24c3001119baa706e9d70c26 | 33 + .../53/e0a18aff24c3001119baa706e9d70c26 | Bin 0 -> 192 bytes .../54/827b93ff24c3001119baa706e9d70c26 | 50 + .../54/83b789ff24c3001119baa706e9d70c26 | 20 + .../54/e0eb28575dc300111ab8b17b137f3789 | 205 ++ .../54/f0e8df4316c3001119baa706e9d70c26 | 1025 ++++++ .../55/54248eff24c3001119baa706e9d70c26 | Bin 0 -> 76 bytes .../55/725493ff24c3001119baa706e9d70c26 | 26 + .../55/d1eb8cff24c3001119baa706e9d70c26 | Bin 0 -> 134 bytes .../56/907ef79c24c3001119baa706e9d70c26 | 216 ++ .../56/b057160f09c3001119baa706e9d70c26 | 1548 +++++++++ .../56/f0f618e311c3001119baa706e9d70c26 | 255 ++ .../57/00128e7e24c500111b2a8b7f47e59881 | 0 .../57/201b61def9c500111689feaa37e8ab14 | 39 + .../57/a0c993ff24c3001119baa706e9d70c26 | 27 + .../57/b033f63c27c500111b2a8b7f47e59881 | 17 + .../57/c2a691ff24c3001119baa706e9d70c26 | Bin 0 -> 1551 bytes .../57/e018401d24c500111b2a8b7f47e59881 | 36 + .../58/30edfe7f0dc3001119baa706e9d70c26 | 17 + .../58/a2e78eff24c3001119baa706e9d70c26 | Bin 0 -> 249 bytes .../59/309a97ff24c3001119baa706e9d70c26 | 245 ++ .../59/609c1e6e52c3001119baa706e9d70c26 | 23 + .../59/a015408c93c500111b2a8b7f47e59881 | 197 ++ .../59/c069972b0dc3001119baa706e9d70c26 | 255 ++ .../59/d07a8aff24c3001119baa706e9d70c26 | Bin 0 -> 2866 bytes .../5a/509590ff24c3001119baa706e9d70c26 | Bin 0 -> 113 bytes .../5a/91c08eff24c3001119baa706e9d70c26 | Bin 0 -> 170 bytes .../5a/b0771c5529c3001119baa706e9d70c26 | 20 + .../5b/108dfe1115c3001119baa706e9d70c26 | 1210 +++++++ .../5b/40fd0505fac500111689feaa37e8ab14 | 39 + .../5b/b30e8fff24c3001119baa706e9d70c26 | Bin 0 -> 148 bytes .../5c/4018fb3525c3001119baa706e9d70c26 | 1180 +++++++ .../5c/c0538aff24c3001119baa706e9d70c26 | Bin 0 -> 138 bytes .../5d/60b6984915c3001119baa706e9d70c26 | 350 ++ .../5d/610f98ff24c3001119baa706e9d70c26 | 170 + .../5d/815d98ff24c3001119baa706e9d70c26 | 818 +++++ .../5e/c06fde164dc3001119baa706e9d70c26 | 217 ++ .../5f/f04cf1390ac3001119baa706e9d70c26 | 255 ++ .../6/715493ff24c3001119baa706e9d70c26 | 26 + .../6/83288cff24c3001119baa706e9d70c26 | Bin 0 -> 2081 bytes .../6/c2538aff24c3001119baa706e9d70c26 | Bin 0 -> 135 bytes .../6/e0bc80581fc3001119baa706e9d70c26 | 1146 ++++++ .../60/146a92ff24c3001119baa706e9d70c26 | Bin 0 -> 149 bytes .../60/a3768cff24c3001119baa706e9d70c26 | Bin 0 -> 458 bytes .../60/b39d8cff24c3001119baa706e9d70c26 | Bin 0 -> 146 bytes .../61/50248eff24c3001119baa706e9d70c26 | Bin 0 -> 332 bytes .../61/703698ff24c3001119baa706e9d70c26 | 447 +++ .../61/70598081f4c500111689feaa37e8ab14 | 41 + .../61/71c595ff24c3001119baa706e9d70c26 | 1111 ++++++ .../61/913191ff24c3001119baa706e9d70c26 | Bin 0 -> 935 bytes .../61/e0548665f4c500111689feaa37e8ab14 | 41 + .../62/601a552352c3001119baa706e9d70c26 | 304 ++ .../62/7015e02226c3001119baa706e9d70c26 | 772 +++++ .../62/c038db3c52c3001119baa706e9d70c26 | Bin 0 -> 2372 bytes .../62/c05b8a4653c3001115d2d454e05194c5 | 5 + .../63/007dfa8d29c500111b2a8b7f47e59881 | 209 ++ .../63/13888dff24c3001119baa706e9d70c26 | Bin 0 -> 105 bytes .../63/9020d055f8c500111689feaa37e8ab14 | 195 ++ .../63/e092273052c3001119baa706e9d70c26 | Bin 0 -> 2030 bytes .../63/f053d17c0dc3001119baa706e9d70c26 | 17 + .../64/306e50a72ac500111b2a8b7f47e59881 | 150 + .../64/435095ff24c3001119baa706e9d70c26 | 253 ++ .../64/6037a5b016c3001119baa706e9d70c26 | 1145 ++++++ .../64/904f8cff24c3001119baa706e9d70c26 | Bin 0 -> 311 bytes .../64/e053992f16c3001119baa706e9d70c26 | 1154 +++++++ .../65/20c526055cc300111ab8b17b137f3789 | 139 + .../65/a4058aff24c3001119baa706e9d70c26 | 34 + .../65/d27a8aff24c3001119baa706e9d70c26 | Bin 0 -> 146 bytes .../66/32658bff24c3001119baa706e9d70c26 | Bin 0 -> 737 bytes .../66/d09cd4b552c3001119baa706e9d70c26 | 143 + .../67/12888dff24c3001119baa706e9d70c26 | Bin 0 -> 109 bytes .../67/30a36c71f5c500111689feaa37e8ab14 | 0 .../67/404991cd28c500111b2a8b7f47e59881 | 36 + .../67/70b352830ac3001119baa706e9d70c26 | 89 + .../67/e029c91e24c500111b2a8b7f47e59881 | 36 + .../68/012597ff24c3001119baa706e9d70c26 | 150 + .../68/924f8cff24c3001119baa706e9d70c26 | Bin 0 -> 306 bytes .../69/50de51fe25c3001119baa706e9d70c26 | 770 +++++ .../69/601e89202cc3001119baa706e9d70c26 | 1182 +++++++ .../69/90053b045cc300111ab8b17b137f3789 | 138 + .../69/d13e94ff24c3001119baa706e9d70c26 | 36 + .../69/e0243f142ec3001119baa706e9d70c26 | 1184 +++++++ .../6a/04618dff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../6a/10178bff24c3001119baa706e9d70c26 | Bin 0 -> 108 bytes .../6a/217397ff24c3001119baa706e9d70c26 | 291 ++ .../6a/739089ff24c3001119baa706e9d70c26 | 18 + .../6b/b09d8cff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../6b/e0d18a5724c3001119baa706e9d70c26 | 216 ++ .../6c/428c8bff24c3001119baa706e9d70c26 | Bin 0 -> 505 bytes .../6c/94c08eff24c3001119baa706e9d70c26 | Bin 0 -> 254 bytes .../6d/b0e576ea0cc3001119baa706e9d70c26 | 721 ++++ .../6d/d0b95e3e26c500111b2a8b7f47e59881 | 7 + .../6e/9038117b2ac500111b2a8b7f47e59881 | 37 + .../6e/e0a5563952c3001119baa706e9d70c26 | Bin 0 -> 1517 bytes .../6f/022597ff24c3001119baa706e9d70c26 | 376 ++ .../6f/207397ff24c3001119baa706e9d70c26 | 72 + .../6f/300b9f5a2ec3001119baa706e9d70c26 | 1182 +++++++ .../6f/30658bff24c3001119baa706e9d70c26 | Bin 0 -> 546 bytes .../6f/506c78ea0cc3001119baa706e9d70c26 | 95 + .../6f/805d98ff24c3001119baa706e9d70c26 | 1131 ++++++ .../6f/9054a9832ec3001119baa706e9d70c26 | 255 ++ .../70/044392ff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../71/10e222d4f9c500111689feaa37e8ab14 | 41 + .../71/507795ff24c3001119baa706e9d70c26 | 1191 +++++++ .../71/d37a8aff24c3001119baa706e9d70c26 | Bin 0 -> 145 bytes .../72/30d68dff24c3001119baa706e9d70c26 | Bin 0 -> 128 bytes .../72/312995ff24c3001119baa706e9d70c26 | 72 + .../72/406170bff8c500111689feaa37e8ab14 | 8 + .../72/60a4603816c3001119baa706e9d70c26 | 1154 +++++++ .../72/a0cf768d1cc3001119baa706e9d70c26 | 1146 ++++++ .../72/e04c6b0426c3001119baa706e9d70c26 | 770 +++++ .../74/00e1273052c3001119baa706e9d70c26 | Bin 0 -> 2349 bytes .../74/032597ff24c3001119baa706e9d70c26 | 148 + .../74/32b892ff24c3001119baa706e9d70c26 | 56 + .../74/a08e698a27c3001119baa706e9d70c26 | 215 ++ .../75/002e00504ec3001119baa706e9d70c26 | 38 + .../75/a0768cff24c3001119baa706e9d70c26 | Bin 0 -> 524 bytes .../75/e0e81e9144c3001119baa706e9d70c26 | 217 ++ .../76/11178bff24c3001119baa706e9d70c26 | Bin 0 -> 149 bytes .../76/20560baaf3c500111689feaa37e8ab14 | 1185 +++++++ .../76/702831bf52c3001119baa706e9d70c26 | 145 + .../76/82288cff24c3001119baa706e9d70c26 | Bin 0 -> 188 bytes .../76/a1058aff24c3001119baa706e9d70c26 | 25 + .../76/c0ea58865bc300111ab8b17b137f3789 | 138 + .../76/e1838fff24c3001119baa706e9d70c26 | Bin 0 -> 157 bytes .../77/719089ff24c3001119baa706e9d70c26 | 25 + .../78/1098152e2cc3001119baa706e9d70c26 | 1183 +++++++ .../78/a0a5d5fb94c500111b2a8b7f47e59881 | 384 +++ .../78/b16196ff24c3001119baa706e9d70c26 | 65 + .../78/f0c6d0d2f6c500111689feaa37e8ab14 | 200 ++ .../79/9058251f40c3001119baa706e9d70c26 | 216 ++ .../7a/40df92ff24c3001119baa706e9d70c26 | 31 + .../7a/70728eff24c3001119baa706e9d70c26 | Bin 0 -> 172 bytes .../7b/219192ff24c3001119baa706e9d70c26 | 7 + .../7b/308b22fbf5c500111689feaa37e8ab14 | 12 + .../7b/32d68dff24c3001119baa706e9d70c26 | Bin 0 -> 622 bytes .../7b/4016ef4f2bc500111b2a8b7f47e59881 | 1877 ++++++++++ .../7b/a0c8141b5cc300111ab8b17b137f3789 | 135 + .../7b/c11794ff24c3001119baa706e9d70c26 | 33 + .../7b/e3a18aff24c3001119baa706e9d70c26 | Bin 0 -> 146 bytes .../7b/f28c94ff24c3001119baa706e9d70c26 | 22 + .../7c/73c595ff24c3001119baa706e9d70c26 | 136 + .../7c/c09972fa50c3001119baa706e9d70c26 | 30 + .../7c/e0fc70511ec3001119baa706e9d70c26 | 778 +++++ .../7d/00b494ff24c3001119baa706e9d70c26 | 22 + .../7d/30b892ff24c3001119baa706e9d70c26 | 6 + .../7d/54e897ff24c3001119baa706e9d70c26 | 545 +++ .../7d/e2f491ff24c3001119baa706e9d70c26 | Bin 0 -> 1160 bytes .../7e/209192ff24c3001119baa706e9d70c26 | 38 + .../7f/20bdc373f6c500111689feaa37e8ab14 | 22 + .../7f/82ec95ff24c3001119baa706e9d70c26 | 227 ++ .../7f/c1a691ff24c3001119baa706e9d70c26 | Bin 0 -> 1362 bytes .../7f/e0a11e2393c500111b2a8b7f47e59881 | 39 + .../8/0094c70a2ac3001119baa706e9d70c26 | 216 ++ .../8/10db94ff24c3001119baa706e9d70c26 | 22 + .../8/537795ff24c3001119baa706e9d70c26 | 1026 ++++++ .../80/529590ff24c3001119baa706e9d70c26 | Bin 0 -> 161 bytes .../80/604f8e870cc3001119baa706e9d70c26 | 253 ++ .../80/84288cff24c3001119baa706e9d70c26 | Bin 0 -> 1811 bytes .../80/92de89ff24c3001119baa706e9d70c26 | 32 + .../80/d17a8aff24c3001119baa706e9d70c26 | Bin 0 -> 2862 bytes .../80/f0a05d91f4c500111689feaa37e8ab14 | 0 .../82/201c6ecf52c3001119baa706e9d70c26 | 145 + .../82/20df03185cc300111ab8b17b137f3789 | 135 + .../82/448c8bff24c3001119baa706e9d70c26 | Bin 0 -> 78 bytes .../82/e1a18aff24c3001119baa706e9d70c26 | Bin 0 -> 146 bytes .../83/009102e229c3001119baa706e9d70c26 | 216 ++ .../83/5085db29f4c500111689feaa37e8ab14 | 1185 +++++++ .../83/6007dfe223c500111b2a8b7f47e59881 | 37 + .../83/f21b92ff24c3001119baa706e9d70c26 | Bin 0 -> 381 bytes .../83/f2fd96ff24c3001119baa706e9d70c26 | 234 ++ .../84/622d93ff24c3001119baa706e9d70c26 | 38 + .../84/a4c993ff24c3001119baa706e9d70c26 | 42 + .../85/4094b6c125c3001119baa706e9d70c26 | 1178 +++++++ .../85/f0c88aff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../86/108d5a6d26c3001119baa706e9d70c26 | 772 +++++ .../86/20f6d7cd2ec3001119baa706e9d70c26 | 643 ++++ .../86/33b892ff24c3001119baa706e9d70c26 | 23 + .../86/421b89ff24c3001119baa706e9d70c26 | 12 + .../86/80288cff24c3001119baa706e9d70c26 | Bin 0 -> 917 bytes .../86/e4a18aff24c3001119baa706e9d70c26 | Bin 0 -> 139 bytes .../87/10efd0432ac500111b2a8b7f47e59881 | 201 ++ .../87/324790ff24c3001119baa706e9d70c26 | Bin 0 -> 108 bytes .../87/415095ff24c3001119baa706e9d70c26 | 253 ++ .../87/90c08eff24c3001119baa706e9d70c26 | Bin 0 -> 170 bytes .../87/c4358fff24c3001119baa706e9d70c26 | Bin 0 -> 155 bytes .../88/00dac57f48c3001119baa706e9d70c26 | 218 ++ .../88/01f08aff24c3001119baa706e9d70c26 | Bin 0 -> 112 bytes .../88/723698ff24c3001119baa706e9d70c26 | 598 ++++ .../89/33d68dff24c3001119baa706e9d70c26 | Bin 0 -> 466 bytes .../89/70f2283052c3001119baa706e9d70c26 | Bin 0 -> 3235 bytes .../89/743698ff24c3001119baa706e9d70c26 | 65 + .../89/907a82e930c500111b2a8b7f47e59881 | 41 + .../89/b0f093ff24c3001119baa706e9d70c26 | 384 +++ .../89/d0305c4a3ec3001119baa706e9d70c26 | 20 + .../8a/11888dff24c3001119baa706e9d70c26 | Bin 0 -> 99 bytes .../8a/40355f4f5dc300111ab8b17b137f3789 | 207 ++ .../8a/c0af62282ac500111b2a8b7f47e59881 | 151 + .../8a/f0127fde52c3001119baa706e9d70c26 | 145 + .../8b/0048e819f8c500111689feaa37e8ab14 | 15 + .../8b/23af8dff24c3001119baa706e9d70c26 | Bin 0 -> 124 bytes .../8b/606e710d16c3001119baa706e9d70c26 | 1154 +++++++ .../8b/92c08eff24c3001119baa706e9d70c26 | Bin 0 -> 1336 bytes .../8b/f01075ea0cc3001119baa706e9d70c26 | 295 ++ .../8c/200b8dcc24c3001119baa706e9d70c26 | 1162 +++++++ .../8c/61bc90ff24c3001119baa706e9d70c26 | Bin 0 -> 161 bytes .../8c/70d9149024c3001119baa706e9d70c26 | 217 ++ .../8c/90de89ff24c3001119baa706e9d70c26 | 28 + .../8c/b07f91ff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../8c/d0c20e8af8c500111689feaa37e8ab14 | 20 + .../8c/d0eb8cff24c3001119baa706e9d70c26 | Bin 0 -> 129 bytes .../8d/30f44a092cc3001119baa706e9d70c26 | 1182 +++++++ .../8d/9007c34315c3001119baa706e9d70c26 | 255 ++ .../8e/304790ff24c3001119baa706e9d70c26 | Bin 0 -> 160 bytes .../8e/50e172181fc3001119baa706e9d70c26 | 1145 ++++++ .../8e/90126ef42bc3001119baa706e9d70c26 | 24 + .../8f/02f08aff24c3001119baa706e9d70c26 | Bin 0 -> 108 bytes .../8f/426e90ff24c3001119baa706e9d70c26 | Bin 0 -> 115 bytes .../8f/80ec95ff24c3001119baa706e9d70c26 | 135 + .../8f/a25891ff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../8f/f05f6a694ec3001119baa706e9d70c26 | 38 + .../9/014392ff24c3001119baa706e9d70c26 | Bin 0 -> 671 bytes .../9/2073b0f72ac500111b2a8b7f47e59881 | 37 + .../9/305425242ac500111b2a8b7f47e59881 | 143 + .../9/507ec6064fc3001119baa706e9d70c26 | 31 + .../9/60759eacf9c500111689feaa37e8ab14 | 41 + .../9/c01794ff24c3001119baa706e9d70c26 | 29 + .../90/b02c8aff24c3001119baa706e9d70c26 | Bin 0 -> 144 bytes .../90/f093d2de30c500111b2a8b7f47e59881 | 39 + .../91/40c38c6824c3001119baa706e9d70c26 | 216 ++ .../91/40d25635f4c500111689feaa37e8ab14 | 1193 +++++++ .../91/e0f09c4a1ec3001119baa706e9d70c26 | 778 +++++ .../93/3047871c16c3001119baa706e9d70c26 | 1154 +++++++ .../93/50d573254ac3001119baa706e9d70c26 | 118 + .../93/52e897ff24c3001119baa706e9d70c26 | 699 ++++ .../93/72728eff24c3001119baa706e9d70c26 | Bin 0 -> 651 bytes .../93/c05cdb825bc300111ab8b17b137f3789 | 138 + .../93/c0d88cd2f9c500111689feaa37e8ab14 | 40 + .../94/00f4563952c3001119baa706e9d70c26 | Bin 0 -> 1915 bytes .../94/03f08aff24c3001119baa706e9d70c26 | Bin 0 -> 110 bytes .../94/33658bff24c3001119baa706e9d70c26 | Bin 0 -> 144 bytes .../94/6068e9cdf9c500111689feaa37e8ab14 | 41 + .../94/63bc90ff24c3001119baa706e9d70c26 | Bin 0 -> 1256 bytes .../94/a0e09e241fc3001119baa706e9d70c26 | 1146 ++++++ .../94/e26594ff24c3001119baa706e9d70c26 | 12 + .../95/309ee17f2ec3001119baa706e9d70c26 | 255 ++ .../95/612d93ff24c3001119baa706e9d70c26 | 56 + .../95/d0c5554c5dc300111ab8b17b137f3789 | 208 ++ .../95/e064c92585c2001119baa706e9d70c26 | 338 ++ .../95/e0c8be1d2ec3001119baa706e9d70c26 | 772 +++++ .../96/10888dff24c3001119baa706e9d70c26 | Bin 0 -> 101 bytes .../96/2003e8bc4fc3001119baa706e9d70c26 | 20 + .../96/817b93ff24c3001119baa706e9d70c26 | 26 + .../96/90657c4f2ec3001119baa706e9d70c26 | 715 ++++ .../97/a1c993ff24c3001119baa706e9d70c26 | 43 + .../98/30a5542352c3001119baa706e9d70c26 | 89 + .../99/002bb3562ec3001119baa706e9d70c26 | 703 ++++ .../99/1089edc6f9c500111689feaa37e8ab14 | 41 + .../99/108c455540c3001119baa706e9d70c26 | 216 ++ .../99/53b38bff24c3001119baa706e9d70c26 | Bin 0 -> 159 bytes .../99/9018d253f6c500111689feaa37e8ab14 | 201 ++ .../99/c06a7fed0cc3001119baa706e9d70c26 | 318 ++ .../99/c09f2a102bc500111b2a8b7f47e59881 | 38 + .../99/f024649ef8c500111689feaa37e8ab14 | 21 + .../9a/400a60aef3c500111689feaa37e8ab14 | 1185 +++++++ .../9a/4044c7f125c3001119baa706e9d70c26 | 1182 +++++++ .../9b/12178bff24c3001119baa706e9d70c26 | Bin 0 -> 145 bytes .../9b/203b390e2ac3001119baa706e9d70c26 | 216 ++ .../9b/232090ff24c3001119baa706e9d70c26 | Bin 0 -> 171 bytes .../9b/40ec4cc82bc3001119baa706e9d70c26 | 24 + .../9b/b07c0ee491c500111b2a8b7f47e59881 | 1548 +++++++++ .../9c/51b38bff24c3001119baa706e9d70c26 | Bin 0 -> 159 bytes .../9c/805daa0f0dc3001119baa706e9d70c26 | 20 + .../9c/9094f77227c500111b2a8b7f47e59881 | 18 + .../9c/c0a415382ec3001119baa706e9d70c26 | 714 ++++ .../9d/3040e8d714c3001119baa706e9d70c26 | 778 +++++ .../9d/62bc90ff24c3001119baa706e9d70c26 | Bin 0 -> 1263 bytes .../9e/60da8bff24c3001119baa706e9d70c26 | Bin 0 -> 159 bytes .../9e/a0ad00d7f9c500111689feaa37e8ab14 | 40 + .../9e/e03197db29c3001119baa706e9d70c26 | 216 ++ .../9f/13178bff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../9f/7021b3484ec3001119baa706e9d70c26 | 30 + .../9f/825d98ff24c3001119baa706e9d70c26 | 316 ++ .../9f/c28896ff24c3001119baa706e9d70c26 | 8 + .../a/116a92ff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../a/5055944bf4c500111689feaa37e8ab14 | 1188 +++++++ .../a/e0f491ff24c3001119baa706e9d70c26 | Bin 0 -> 184 bytes .../a0/11f98fff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../a0/f02ff42df6c500111689feaa37e8ab14 | 19 + .../a0/f1c88aff24c3001119baa706e9d70c26 | Bin 0 -> 155 bytes .../a2/10336a830ac3001119baa706e9d70c26 | 203 ++ .../a2/339a97ff24c3001119baa706e9d70c26 | 40 + .../a2/60ecce2f22c3001119baa706e9d70c26 | 216 ++ .../a3/a3058aff24c3001119baa706e9d70c26 | 34 + .../a4/42fd8dff24c3001119baa706e9d70c26 | Bin 0 -> 122 bytes .../a4/807b93ff24c3001119baa706e9d70c26 | 26 + .../a4/f06925abf9c500111689feaa37e8ab14 | 41 + .../a4/f2aa8fff24c3001119baa706e9d70c26 | Bin 0 -> 152 bytes .../a5/70da467615c3001119baa706e9d70c26 | 1028 ++++++ .../a5/8080ed4ef6c500111689feaa37e8ab14 | 198 ++ .../a5/c04c6a0226c3001119baa706e9d70c26 | 770 +++++ .../a6/42c197ff24c3001119baa706e9d70c26 | 479 +++ .../a7/b0ef28552ac500111b2a8b7f47e59881 | 197 ++ .../a7/e0838fff24c3001119baa706e9d70c26 | Bin 0 -> 165 bytes .../a7/e086db3c52c3001119baa706e9d70c26 | Bin 0 -> 955 bytes .../a8/c03c2a545bc300111ab8b17b137f3789 | 136 + .../a9/207a7344fac500111689feaa37e8ab14 | 197 ++ .../a9/30af1c540ec3001119baa706e9d70c26 | 255 ++ .../a9/c0215a9316c3001119baa706e9d70c26 | 1150 +++++++ .../aa/40e1d7525dc300111ab8b17b137f3789 | 205 ++ .../ab/202090ff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../ab/403eb6a027c500111b2a8b7f47e59881 | 19 + .../ab/527795ff24c3001119baa706e9d70c26 | 95 + .../ac/304e556d2cc3001119baa706e9d70c26 | 1183 +++++++ .../ac/405095ff24c3001119baa706e9d70c26 | 347 ++ .../ad/90135f3f49c3001119baa706e9d70c26 | 218 ++ .../ad/c0155d284ec3001119baa706e9d70c26 | 5 + .../ae/212090ff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../af/f2398dff24c3001119baa706e9d70c26 | Bin 0 -> 134 bytes .../b0/20bac3355dc300111ab8b17b137f3789 | 39 + .../b0/60662a0d2ec3001119baa706e9d70c26 | 1182 +++++++ .../b0/923191ff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../b0/b0d2f59752c3001119baa706e9d70c26 | 20 + .../b0/d03e94ff24c3001119baa706e9d70c26 | 33 + .../b0/d2eb8cff24c3001119baa706e9d70c26 | Bin 0 -> 123 bytes .../b1/300e77481fc3001119baa706e9d70c26 | 1146 ++++++ .../b1/604b8eff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../b1/7005ba380ac3001119baa706e9d70c26 | 253 ++ .../b1/f00258ec26c3001119baa706e9d70c26 | 215 ++ .../b2/10348a342ec3001119baa706e9d70c26 | 714 ++++ .../b2/43df92ff24c3001119baa706e9d70c26 | 46 + .../b2/b0551c03fac500111689feaa37e8ab14 | 39 + .../b2/c1c48cff24c3001119baa706e9d70c26 | Bin 0 -> 134 bytes .../b3/40481c3052c3001119baa706e9d70c26 | Bin 0 -> 2418 bytes .../b4/81288cff24c3001119baa706e9d70c26 | Bin 0 -> 188 bytes .../b4/c0358fff24c3001119baa706e9d70c26 | Bin 0 -> 151 bytes .../b4/c0b1d4870dc3001119baa706e9d70c26 | 18 + .../b5/00a545fd52c3001119baa706e9d70c26 | 4 + .../b5/8042022029c3001119baa706e9d70c26 | 19 + .../b5/a1768cff24c3001119baa706e9d70c26 | Bin 0 -> 523 bytes .../b6/00d28fff24c3001119baa706e9d70c26 | Bin 0 -> 2869 bytes .../b6/1020ba2b25c3001119baa706e9d70c26 | 1181 +++++++ .../b6/24af8dff24c3001119baa706e9d70c26 | Bin 0 -> 130 bytes .../b6/80379b1b2cc3001119baa706e9d70c26 | 1182 +++++++ .../b6/a0058aff24c3001119baa706e9d70c26 | 34 + .../b6/a0e3b66df4c500111689feaa37e8ab14 | 41 + .../b7/c18896ff24c3001119baa706e9d70c26 | 6 + .../b7/e2128dff24c3001119baa706e9d70c26 | Bin 0 -> 122 bytes .../b8/90aa1d6f0ac3001119baa706e9d70c26 | 350 ++ .../b8/f0543b872ec3001119baa706e9d70c26 | 350 ++ .../b8/f3c88aff24c3001119baa706e9d70c26 | Bin 0 -> 104 bytes .../b9/805477ca27c500111b2a8b7f47e59881 | 31 + .../b9/914f8cff24c3001119baa706e9d70c26 | Bin 0 -> 312 bytes .../b9/e06a3a3c10c3001119baa706e9d70c26 | 255 ++ .../b9/e2d696ff24c3001119baa706e9d70c26 | 278 ++ .../ba/2002f03b15c3001119baa706e9d70c26 | 255 ++ .../ba/931396ff24c3001119baa706e9d70c26 | 79 + .../bb/20af8dff24c3001119baa706e9d70c26 | Bin 0 -> 107 bytes .../bb/20d7532a16c3001119baa706e9d70c26 | 1154 +++++++ .../bb/52248eff24c3001119baa706e9d70c26 | Bin 0 -> 151 bytes .../bc/10f98fff24c3001119baa706e9d70c26 | Bin 0 -> 290 bytes .../bc/705493ff24c3001119baa706e9d70c26 | 36 + .../bc/903191ff24c3001119baa706e9d70c26 | Bin 0 -> 699 bytes .../bc/e002f968f3c500111689feaa37e8ab14 | 1181 +++++++ .../bd/308e08963dc3001119baa706e9d70c26 | 19 + .../bd/804a8bb591c500111b2a8b7f47e59881 | 197 ++ .../bd/81ec95ff24c3001119baa706e9d70c26 | 361 ++ .../be/00b9f6452cc3001119baa706e9d70c26 | 1183 +++++++ .../be/21af8dff24c3001119baa706e9d70c26 | Bin 0 -> 105 bytes .../be/a04a6a8e0cc3001119baa706e9d70c26 | 253 ++ .../bf/7021a05c25c3001119baa706e9d70c26 | 1179 +++++++ .../bf/807c6b3949c3001119baa706e9d70c26 | 218 ++ .../bf/9021e1b05bc300111ab8b17b137f3789 | 138 + .../bf/90b3badcf8c500111689feaa37e8ab14 | 5 + .../bf/e0d01f1995c500111b2a8b7f47e59881 | 384 +++ .../c0/102a1f3c26c500111b2a8b7f47e59881 | 7 + .../c0/4023f514f3c500111689feaa37e8ab14 | 1025 ++++++ .../c0/40afb916f6c500111689feaa37e8ab14 | 18 + .../c0/411b89ff24c3001119baa706e9d70c26 | 186 + .../c0/71728eff24c3001119baa706e9d70c26 | Bin 0 -> 171 bytes .../c0/9040293052c3001119baa706e9d70c26 | Bin 0 -> 1501 bytes .../c0/a15891ff24c3001119baa706e9d70c26 | Bin 0 -> 83 bytes .../c0/c0c48cff24c3001119baa706e9d70c26 | Bin 0 -> 145 bytes .../c0/e0128dff24c3001119baa706e9d70c26 | Bin 0 -> 123 bytes .../c1/425095ff24c3001119baa706e9d70c26 | 72 + .../c1/7013a1ff4dc3001119baa706e9d70c26 | 209 ++ .../c1/c057563952c3001119baa706e9d70c26 | Bin 0 -> 1429 bytes .../c2/10bda06a4ec3001119baa706e9d70c26 | 38 + .../c2/a3e78eff24c3001119baa706e9d70c26 | Bin 0 -> 417 bytes .../c3/106dde3c52c3001119baa706e9d70c26 | Bin 0 -> 2582 bytes .../c3/80998eff24c3001119baa706e9d70c26 | Bin 0 -> 165 bytes .../c3/80b442fd23c500111b2a8b7f47e59881 | 205 ++ .../c3/93de89ff24c3001119baa706e9d70c26 | 32 + .../c4/70208f3228c500111b2a8b7f47e59881 | 35 + .../c5/233e8bff24c3001119baa706e9d70c26 | Bin 0 -> 602 bytes .../c5/c08896ff24c3001119baa706e9d70c26 | 148 + .../c5/d049ec4e4ac3001119baa706e9d70c26 | 30 + .../c6/70c1ac002ac3001119baa706e9d70c26 | 1182 +++++++ .../c6/733698ff24c3001119baa706e9d70c26 | 110 + .../c6/c1358fff24c3001119baa706e9d70c26 | Bin 0 -> 150 bytes .../c7/005090eef5c500111689feaa37e8ab14 | 12 + .../c7/624b8eff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../c7/d3cd91ff24c3001119baa706e9d70c26 | Bin 0 -> 1309 bytes .../c7/f0b942944bc3001119baa706e9d70c26 | 20 + .../c8/9038a7ce24c3001119baa706e9d70c26 | 1181 +++++++ .../c8/93c08eff24c3001119baa706e9d70c26 | Bin 0 -> 1165 bytes .../c9/314790ff24c3001119baa706e9d70c26 | Bin 0 -> 109 bytes .../c9/40fd8dff24c3001119baa706e9d70c26 | Bin 0 -> 566 bytes .../c9/416e90ff24c3001119baa706e9d70c26 | Bin 0 -> 113 bytes .../c9/438c8bff24c3001119baa706e9d70c26 | Bin 0 -> 154 bytes .../c9/b07438830ac3001119baa706e9d70c26 | 145 + .../ca/20a5994249c3001119baa706e9d70c26 | 218 ++ .../ca/90aabe775bc300111ab8b17b137f3789 | 138 + .../ca/f08c94ff24c3001119baa706e9d70c26 | 118 + .../cb/102615a1f6c500111689feaa37e8ab14 | 199 ++ .../cb/40c197ff24c3001119baa706e9d70c26 | 44 + .../cb/9018bc4f2cc3001119baa706e9d70c26 | 1183 +++++++ .../cb/b10e8fff24c3001119baa706e9d70c26 | Bin 0 -> 370 bytes .../cc/4059872d15c3001119baa706e9d70c26 | 1212 +++++++ .../cc/406d95885bc300111ab8b17b137f3789 | 138 + .../cc/e0bdb22952c3001119baa706e9d70c26 | 19 + .../cd/202ecd5df6c500111689feaa37e8ab14 | 196 ++ .../cd/709089ff24c3001119baa706e9d70c26 | 21 + .../cd/80e5b6db42c3001119baa706e9d70c26 | 1181 +++++++ .../cd/c0c9d4312bc500111b2a8b7f47e59881 | 196 ++ .../ce/00ae1d4746c3001119baa706e9d70c26 | 1025 ++++++ .../ce/1084ff275cc300111ab8b17b137f3789 | 134 + .../ce/332995ff24c3001119baa706e9d70c26 | 72 + .../ce/60fc548c52c3001119baa706e9d70c26 | 25 + .../ce/634b8eff24c3001119baa706e9d70c26 | Bin 0 -> 158 bytes .../ce/d0af96ff24c3001119baa706e9d70c26 | 264 ++ .../ce/e0d696ff24c3001119baa706e9d70c26 | 572 +++ .../cf/706fcb505dc300111ab8b17b137f3789 | 206 ++ .../cf/a05215462ec3001119baa706e9d70c26 | 716 ++++ .../cf/b29d8cff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../cf/d01a23110dc3001119baa706e9d70c26 | 17 + .../d/50bd96002bc500111b2a8b7f47e59881 | 38 + .../d/517795ff24c3001119baa706e9d70c26 | 318 ++ .../d/60473271f7c500111689feaa37e8ab14 | 200 ++ .../d/c0a691ff24c3001119baa706e9d70c26 | Bin 0 -> 188 bytes .../d0/005d1d5f52c3001119baa706e9d70c26 | 27 + .../d0/92a293ff24c3001119baa706e9d70c26 | 22 + .../d0/d06f13f90cc3001119baa706e9d70c26 | 777 +++++ .../d1/10443768f4c500111689feaa37e8ab14 | 41 + .../d1/10ee022a31c500111b2a8b7f47e59881 | 196 ++ .../d1/406b197ef5c500111689feaa37e8ab14 | 5 + .../d1/c3538aff24c3001119baa706e9d70c26 | Bin 0 -> 134 bytes .../d2/00f08aff24c3001119baa706e9d70c26 | Bin 0 -> 102 bytes .../d2/7099c78429c500111b2a8b7f47e59881 | 208 ++ .../d3/0075e3221fc3001119baa706e9d70c26 | 1146 ++++++ .../d3/b0f8be0224c500111b2a8b7f47e59881 | 205 ++ .../d3/d2cd91ff24c3001119baa706e9d70c26 | Bin 0 -> 1309 bytes .../d4/80b789ff24c3001119baa706e9d70c26 | 27 + .../d5/c047458a2ac500111b2a8b7f47e59881 | 37 + .../d6/60c50ddd23c500111b2a8b7f47e59881 | 38 + .../d6/614b8eff24c3001119baa706e9d70c26 | Bin 0 -> 151 bytes .../d6/b000bdac16c3001119baa706e9d70c26 | 1146 ++++++ .../d7/a0e78eff24c3001119baa706e9d70c26 | Bin 0 -> 255 bytes .../d8/90b213a8f8c500111689feaa37e8ab14 | 22 + .../d8/a2c993ff24c3001119baa706e9d70c26 | 50 + .../d9/e0175dd428c500111b2a8b7f47e59881 | 38 + .../da/20cc06314ec3001119baa706e9d70c26 | 6 + .../da/709dc68093c500111b2a8b7f47e59881 | 197 ++ .../db/70c595ff24c3001119baa706e9d70c26 | 54 + .../db/713698ff24c3001119baa706e9d70c26 | 472 +++ .../db/e1f491ff24c3001119baa706e9d70c26 | Bin 0 -> 184 bytes .../dc/10ab82973dc3001119baa706e9d70c26 | 20 + .../dc/90a293ff24c3001119baa706e9d70c26 | 49 + .../dc/c0f743ac95c500111b2a8b7f47e59881 | 39 + .../dc/f06061c914c3001119baa706e9d70c26 | 760 ++++ .../dd/73728eff24c3001119baa706e9d70c26 | Bin 0 -> 720 bytes .../dd/800dc70c2ac3001119baa706e9d70c26 | 216 ++ .../de/30efe0e725c3001119baa706e9d70c26 | 215 ++ .../df/204547f6f9c500111689feaa37e8ab14 | 40 + .../df/d0fccccff6c500111689feaa37e8ab14 | 199 ++ .../df/e00126e023c500111b2a8b7f47e59881 | 37 + .../e/024392ff24c3001119baa706e9d70c26 | Bin 0 -> 609 bytes .../e0/204a863e25c3001119baa706e9d70c26 | 214 ++ .../e0/41c197ff24c3001119baa706e9d70c26 | 64 + .../e0/509cd0de29c500111b2a8b7f47e59881 | 134 + .../e0/50b38bff24c3001119baa706e9d70c26 | Bin 0 -> 76 bytes .../e0/524289ff24c3001119baa706e9d70c26 | 24 + .../e0/80b3233a4ac3001119baa706e9d70c26 | 28 + .../e0/820a91ff24c3001119baa706e9d70c26 | Bin 0 -> 184 bytes .../e1/00d96a71f6c500111689feaa37e8ab14 | 196 ++ .../e1/63da8bff24c3001119baa706e9d70c26 | Bin 0 -> 922 bytes .../e1/70e088d829c3001119baa706e9d70c26 | 215 ++ .../e2/406e90ff24c3001119baa706e9d70c26 | Bin 0 -> 112 bytes .../e2/41fd8dff24c3001119baa706e9d70c26 | Bin 0 -> 552 bytes .../e2/50a4283052c3001119baa706e9d70c26 | Bin 0 -> 953 bytes .../e2/60a7b2caf9c500111689feaa37e8ab14 | 42 + .../e2/a13a96ff24c3001119baa706e9d70c26 | 65 + .../e2/b04834e62ac500111b2a8b7f47e59881 | 159 + .../e3/136a92ff24c3001119baa706e9d70c26 | Bin 0 -> 166 bytes .../e3/b06196ff24c3001119baa706e9d70c26 | 41 + .../e3/e06594ff24c3001119baa706e9d70c26 | 19 + .../e3/e0f3201785c2001119baa706e9d70c26 | 1473 ++++++++ .../e4/10e6ec4e4ac3001119baa706e9d70c26 | 121 + .../e4/520693ff24c3001119baa706e9d70c26 | 24 + .../e4/70d9e47415c3001119baa706e9d70c26 | 1029 ++++++ .../e4/805d61b9f9c500111689feaa37e8ab14 | 41 + .../e5/20c2ed1b1dc3001119baa706e9d70c26 | 216 ++ .../e5/20d4b2be28c500111b2a8b7f47e59881 | 36 + .../e5/70ada704f6c500111689feaa37e8ab14 | 12 + .../e6/81b789ff24c3001119baa706e9d70c26 | 27 + .../e6/d3af96ff24c3001119baa706e9d70c26 | 721 ++++ .../e7/126a92ff24c3001119baa706e9d70c26 | Bin 0 -> 148 bytes .../e7/f07cf8c726c3001119baa706e9d70c26 | 215 ++ .../e8/20a470ea0cc3001119baa706e9d70c26 | 1548 +++++++++ .../e8/62da8bff24c3001119baa706e9d70c26 | Bin 0 -> 189 bytes .../e8/d06d700253c3001119baa706e9d70c26 | 5 + .../e8/e3128dff24c3001119baa706e9d70c26 | Bin 0 -> 133 bytes .../e9/90fd3c83f4c500111689feaa37e8ab14 | 41 + .../eb/02d28fff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../eb/401b89ff24c3001119baa706e9d70c26 | 15 + .../eb/60bc90ff24c3001119baa706e9d70c26 | Bin 0 -> 174 bytes .../eb/803c9c0328c500111b2a8b7f47e59881 | 33 + .../ec/01d28fff24c3001119baa706e9d70c26 | Bin 0 -> 163 bytes .../ec/114c97ff24c3001119baa706e9d70c26 | 180 + .../ec/f01dc6bbf8c500111689feaa37e8ab14 | 7 + .../ed/90be72830ac3001119baa706e9d70c26 | 1874 ++++++++++ .../ed/d01e0b5415c3001119baa706e9d70c26 | 255 ++ .../ee/c2358fff24c3001119baa706e9d70c26 | Bin 0 -> 150 bytes .../ef/101b573952c3001119baa706e9d70c26 | Bin 0 -> 952 bytes .../ef/10a7ac4b2ac500111b2a8b7f47e59881 | 201 ++ .../ef/60b92661f6c500111689feaa37e8ab14 | 195 ++ .../ef/d0cd91ff24c3001119baa706e9d70c26 | Bin 0 -> 174 bytes .../ef/f18c94ff24c3001119baa706e9d70c26 | 28 + .../f/0046de3c52c3001119baa706e9d70c26 | Bin 0 -> 1768 bytes .../f/03618dff24c3001119baa706e9d70c26 | Bin 0 -> 139 bytes .../f/2001a1f3f5c500111689feaa37e8ab14 | 12 + .../f/83ec95ff24c3001119baa706e9d70c26 | 491 +++ .../f/908498ff24c3001119baa706e9d70c26 | 39 + .../f/f31b92ff24c3001119baa706e9d70c26 | Bin 0 -> 381 bytes .../f0/104c97ff24c3001119baa706e9d70c26 | 120 + .../f0/213e8bff24c3001119baa706e9d70c26 | Bin 0 -> 1414 bytes .../f0/40f1ff8d26c3001119baa706e9d70c26 | 1182 +++++++ .../f0/801e582a27c500111b2a8b7f47e59881 | 16 + .../f0/b042b8554ec3001119baa706e9d70c26 | 37 + .../f0/b19d8cff24c3001119baa706e9d70c26 | Bin 0 -> 148 bytes .../f0/d022329526c3001119baa706e9d70c26 | 1182 +++++++ .../f0/d075347f50c3001119baa706e9d70c26 | 31 + .../f1/81998eff24c3001119baa706e9d70c26 | Bin 0 -> 159 bytes .../f2/602d93ff24c3001119baa706e9d70c26 | 57 + .../f2/d2af96ff24c3001119baa706e9d70c26 | 295 ++ .../f3/008829b329c500111b2a8b7f47e59881 | 210 ++ .../f3/2094de3c52c3001119baa706e9d70c26 | Bin 0 -> 2406 bytes .../f3/407cadf691c500111b2a8b7f47e59881 | 1548 +++++++++ .../f3/60cf24294ac3001119baa706e9d70c26 | 121 + .../f3/a0ea34e4f8c500111689feaa37e8ab14 | 196 ++ .../f4/70018cff24c3001119baa706e9d70c26 | Bin 0 -> 1061 bytes .../f4/80386628f6c500111689feaa37e8ab14 | 17 + .../f4/b20e8fff24c3001119baa706e9d70c26 | Bin 0 -> 370 bytes .../f5/00717c57f8c500111689feaa37e8ab14 | 196 ++ .../f5/203e8bff24c3001119baa706e9d70c26 | Bin 0 -> 147 bytes .../f5/2072c80454c3001115d2d454e05194c5 | 34 + .../f5/901396ff24c3001119baa706e9d70c26 | 1012 ++++++ .../f6/002ffafc50c3001119baa706e9d70c26 | 21 + .../f6/00e68715f6c500111689feaa37e8ab14 | 12 + .../f6/90abdc014ec3001119baa706e9d70c26 | 20 + .../f7/50c9c9910cc3001119baa706e9d70c26 | 253 ++ .../f7/e0b5afb7f9c500111689feaa37e8ab14 | 41 + .../f7/f0ec1f0e0dc3001119baa706e9d70c26 | 20 + .../f8/11e6ec4e4ac3001119baa706e9d70c26 | 29 + .../f8/5067ce9f5bc300111ab8b17b137f3789 | 138 + .../f8/d0cef5e90cc3001119baa706e9d70c26 | 291 ++ .../f9/44df92ff24c3001119baa706e9d70c26 | 26 + .../f9/61da8bff24c3001119baa706e9d70c26 | Bin 0 -> 189 bytes .../f9/921396ff24c3001119baa706e9d70c26 | 1265 +++++++ .../f9/a005ca4d26c500111b2a8b7f47e59881 | 7 + .../fa/004a499242c3001119baa706e9d70c26 | 1181 +++++++ .../fa/70e390ff24c3001119baa706e9d70c26 | Bin 0 -> 741 bytes .../fa/a2768cff24c3001119baa706e9d70c26 | Bin 0 -> 464 bytes .../fb/209cea4e4ac3001119baa706e9d70c26 | 12 + .../fc/9080fd0f4fc3001119baa706e9d70c26 | 67 + .../fc/f0d090c514c3001119baa706e9d70c26 | 778 +++++ .../fd/30f488ff24c3001119baa706e9d70c26 | 6 + .../fd/5056cd32f6c500111689feaa37e8ab14 | 198 ++ .../fd/50c1c6d325c3001119baa706e9d70c26 | 215 ++ .../fd/804c0dfe2bc3001119baa706e9d70c26 | 24 + .../fd/d0f3e8b693c500111b2a8b7f47e59881 | 197 ++ .../fe/b029bb50f8c500111689feaa37e8ab14 | 196 ++ .../fe/d05c8fff24c3001119baa706e9d70c26 | 34 + .../fe/e09b7f8424c3001119baa706e9d70c26 | 1144 ++++++ .../ff/109445830ac3001119baa706e9d70c26 | 1472 ++++++++ .../ff/40d5f01c54c3001115d2d454e05194c5 | 16 + .../.indexes/a0/30/properties.index | Bin 0 -> 228 bytes .../.indexes/a0/32/properties.index | Bin 0 -> 166 bytes .../.indexes/a0/3a/properties.index | Bin 0 -> 304 bytes .../.indexes/a0/4a/properties.index | Bin 0 -> 335 bytes .../.indexes/a0/54/properties.index | Bin 0 -> 273 bytes .../.indexes/a0/62/properties.index | Bin 0 -> 2416 bytes .../.indexes/a0/63/properties.index | Bin 0 -> 550 bytes .../.indexes/a0/67/properties.index | Bin 0 -> 179 bytes .../.indexes/a0/77/properties.index | Bin 0 -> 184 bytes .../.indexes/a0/81/properties.index | Bin 0 -> 179 bytes .../.indexes/a0/93/properties.index | Bin 0 -> 166 bytes .../.indexes/a0/cb/properties.index | Bin 0 -> 166 bytes .../.indexes/a0/cd/properties.index | Bin 0 -> 275 bytes .../.indexes/a0/d6/properties.index | Bin 0 -> 2703 bytes .../.indexes/a0/d8/properties.index | Bin 0 -> 181 bytes .../.indexes/a0/de/history.index | Bin 0 -> 84 bytes .../.indexes/a0/de/properties.index | Bin 0 -> 1178 bytes .../.indexes/a0/e/properties.index | Bin 0 -> 247 bytes .../.indexes/a0/eb/history.index | Bin 0 -> 64 bytes .../.indexes/a0/ee/history.index | Bin 0 -> 219 bytes .../.indexes/a0/f6/properties.index | Bin 0 -> 297 bytes .../.indexes/a0/fa/properties.index | Bin 0 -> 242 bytes .../.indexes/bb/92/81/a/bd/history.index | Bin 0 -> 102 bytes .../.indexes/bb/a0/30/history.index | Bin 0 -> 74 bytes .../.indexes/bb/a0/32/history.index | Bin 0 -> 75 bytes .../.indexes/bb/a0/3a/history.index | Bin 0 -> 175 bytes .../.indexes/bb/a0/3c/history.index | Bin 0 -> 6435 bytes .../.indexes/bb/a0/4a/history.index | Bin 0 -> 143 bytes .../.indexes/bb/a0/54/history.index | Bin 0 -> 144 bytes .../.indexes/bb/a0/61/history.index | Bin 0 -> 6439 bytes .../.indexes/bb/a0/62/history.index | Bin 0 -> 1641 bytes .../.indexes/bb/a0/63/history.index | Bin 0 -> 345 bytes .../.indexes/bb/a0/67/history.index | Bin 0 -> 88 bytes .../.indexes/bb/a0/77/history.index | Bin 0 -> 93 bytes .../.indexes/bb/a0/81/history.index | Bin 0 -> 88 bytes .../.indexes/bb/a0/82/history.index | Bin 0 -> 6509 bytes .../.indexes/bb/a0/93/history.index | Bin 0 -> 75 bytes .../.indexes/bb/a0/cb/history.index | Bin 0 -> 75 bytes .../.indexes/bb/a0/cd/history.index | Bin 0 -> 146 bytes .../.indexes/bb/a0/d6/history.index | Bin 0 -> 1713 bytes .../.indexes/bb/a0/d8/history.index | Bin 0 -> 90 bytes .../.indexes/bb/a0/de/history.index | Bin 0 -> 568 bytes .../.indexes/bb/a0/e/history.index | Bin 0 -> 93 bytes .../.indexes/bb/a0/eb/history.index | Bin 0 -> 72 bytes .../.indexes/bb/a0/ee/history.index | Bin 0 -> 139 bytes .../.indexes/bb/a0/f6/history.index | Bin 0 -> 168 bytes .../.indexes/bb/a0/fa/history.index | Bin 0 -> 88 bytes .../.indexes/bb/e4/81/a/21/history.index | Bin 0 -> 836 bytes .../.indexes/bb/e4/81/a/a5/history.index | Bin 0 -> 671 bytes .../.indexes/bb/e4/81/a/bc/history.index | Bin 0 -> 288 bytes .../bb/e4/81/a/bd/19/84/history.index | Bin 0 -> 1521 bytes .../bb/e4/81/a/bd/19/a5/84/history.index | Bin 0 -> 126 bytes .../bb/e4/81/a/bd/19/a5/history.index | Bin 0 -> 116 bytes .../bb/e4/81/a/bd/19/bc/history.index | Bin 0 -> 360 bytes .../.indexes/bb/e4/81/a/bd/21/history.index | Bin 0 -> 196 bytes .../bb/e4/81/a/bd/a5/5f/history.index | Bin 0 -> 1812 bytes .../.indexes/bb/e4/81/a/bd/a5/history.index | Bin 0 -> 434 bytes .../.indexes/bb/e4/81/a/bd/bc/history.index | Bin 0 -> 1507 bytes .../.indexes/bb/e4/81/a/bd/history.index | Bin 0 -> 297 bytes .../.indexes/bb/e4/81/a/history.index | Bin 0 -> 90 bytes .../.indexes/bb/history.index | Bin 0 -> 206 bytes .../.indexes/e4/81/a/21/history.index | Bin 0 -> 897 bytes .../.indexes/e4/81/a/bd/21/history.index | Bin 0 -> 307 bytes .../.indexes/e4/81/a/bd/a5/5f/history.index | Bin 0 -> 200 bytes .../.indexes/e4/81/a/bd/bc/history.index | Bin 0 -> 282 bytes .../.indexes/e4/81/a/bd/history.index | Bin 0 -> 297 bytes .../.indexes/e4/81/a/history.index | Bin 0 -> 2160 bytes .../.indexes/properties.index | Bin 0 -> 658 bytes .../ActionBarSherlockSlidingMenu/.markers | Bin 0 -> 16174 bytes .../.markers.snap | Bin 0 -> 53153 bytes .../.syncinfo.snap | Bin 0 -> 144 bytes .../example/.indexes/a0/5f/history.index | Bin 0 -> 99 bytes .../example/.indexes/a0/5f/properties.index | Bin 0 -> 213 bytes .../example/.indexes/a0/d6/properties.index | Bin 0 -> 247 bytes .../example/.indexes/a0/de/properties.index | Bin 0 -> 314 bytes .../.indexes/e4/81/73/96/history.index | Bin 0 -> 1642 bytes .../.projects/example/.indexes/history.index | Bin 0 -> 245 bytes .../example/.indexes/properties.index | Bin 0 -> 664 bytes .../.projects/example/.markers | Bin 0 -> 863 bytes .../.projects/example/.markers.snap | Bin 0 -> 7827 bytes .../.projects/example/.syncinfo.snap | Bin 0 -> 144 bytes .../library/.indexes/a0/3c/history.index | Bin 0 -> 397 bytes .../library/.indexes/a0/3d/properties.index | Bin 0 -> 176 bytes .../library/.indexes/a0/5f/history.index | Bin 0 -> 51 bytes .../library/.indexes/a0/61/history.index | Bin 0 -> 397 bytes .../library/.indexes/a0/62/history.index | Bin 0 -> 276 bytes .../library/.indexes/a0/82/history.index | Bin 0 -> 338 bytes .../library/.indexes/a0/d6/history.index | Bin 0 -> 355 bytes .../library/.indexes/a0/d6/properties.index | Bin 0 -> 751 bytes .../library/.indexes/a0/de/history.index | Bin 0 -> 639 bytes .../library/.indexes/a0/de/properties.index | Bin 0 -> 216 bytes .../library/.indexes/a0/f3/history.index | Bin 0 -> 85 bytes .../.indexes/e4/81/73/85/1d/history.index | Bin 0 -> 381 bytes .../.indexes/e4/81/73/85/21/history.index | Bin 0 -> 1952 bytes .../.indexes/e4/81/73/85/history.index | Bin 0 -> 3106 bytes .../.projects/library/.indexes/history.index | Bin 0 -> 77 bytes .../library/.indexes/properties.index | Bin 0 -> 766 bytes .../.projects/library/.markers | Bin 0 -> 6734 bytes .../.projects/library/.markers.snap | Bin 0 -> 38432 bytes .../.projects/library/.syncinfo.snap | Bin 0 -> 144 bytes .../.root/.indexes/history.version | 1 + .../.root/.indexes/properties.index | Bin 0 -> 245 bytes .../.root/.indexes/properties.version | 1 + .../org.eclipse.core.resources/.root/.markers | Bin 0 -> 1816 bytes .../.root/.markers.snap | Bin 0 -> 1976 bytes .../org.eclipse.core.resources/.root/4.tree | Bin 0 -> 92652 bytes .../.safetable/org.eclipse.core.resources | Bin 0 -> 4976 bytes .../.plugins/org.eclipse.core.resources/.snap | Bin 0 -> 123153 bytes .../com.android.ide.eclipse.adt.prefs | 3 + .../com.android.ide.eclipse.ddms.prefs | 8 + .../.settings/net.rim.ajde.prefs | 2 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.debug.core.prefs | 2 + .../.settings/org.eclipse.debug.ui.prefs | 6 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../.settings/org.eclipse.jdt.debug.ui.prefs | 2 + .../.settings/org.eclipse.jdt.launching.prefs | 2 + .../.settings/org.eclipse.jdt.ui.prefs | 19 + .../.settings/org.eclipse.search.prefs | 2 + .../.settings/org.eclipse.ui.browser.prefs | 2 + .../.settings/org.eclipse.ui.editors.prefs | 2 + .../.settings/org.eclipse.ui.ide.prefs | 5 + .../.settings/org.eclipse.ui.prefs | 2 + .../.settings/org.eclipse.wst.sse.core.prefs | 2 + .../.settings/org.eclipse.wst.sse.ui.prefs | 4 + .../.launches/example.launch | 19 + .../org.eclipse.debug.ui/dialog_settings.xml | 8 + .../launchConfigurationHistory.xml | 23 + .../org.eclipse.jdt.core/1440040889.index | Bin 0 -> 193980 bytes .../org.eclipse.jdt.core/1577419489.index | Bin 0 -> 27289 bytes .../org.eclipse.jdt.core/1717276877.index | Bin 0 -> 139143 bytes .../org.eclipse.jdt.core/1809425343.index | Bin 0 -> 1487351 bytes .../org.eclipse.jdt.core/2040064081.index | Bin 0 -> 52626 bytes .../org.eclipse.jdt.core/2240772384.index | Bin 0 -> 178804 bytes .../org.eclipse.jdt.core/2942843900.index | Bin 0 -> 869 bytes .../org.eclipse.jdt.core/3058661946.index | Bin 0 -> 1494519 bytes .../org.eclipse.jdt.core/3069504370.index | Bin 0 -> 32457 bytes .../org.eclipse.jdt.core/4000112963.index | Bin 0 -> 139143 bytes .../externalLibsTimeStamps | Bin 0 -> 514 bytes .../org.eclipse.jdt.core/invalidArchivesCache | Bin 0 -> 4 bytes .../org.eclipse.jdt.core/javaLikeNames.txt | 1 + .../org.eclipse.jdt.core/nonChainingJarsCache | Bin 0 -> 504 bytes .../org.eclipse.jdt.core/savedIndexNames.txt | 10 + .../variablesAndContainers.dat | Bin 0 -> 1223 bytes .../dialog_settings.xml | 3 + .../org.eclipse.jdt.launching/.install.xml | 4 + .../libraryInfos.xml | 25 + .../org.eclipse.jdt.ui/OpenTypeHistory.xml | 2 + .../QualifiedTypeNameHistory.xml | 19 + .../org.eclipse.jdt.ui/dialog_settings.xml | 49 + .../org.eclipse.jdt.ui/jdt-images/0.png | Bin 0 -> 210 bytes .../org.eclipse.jdt.ui/jdt-images/1.png | Bin 0 -> 478 bytes .../org.eclipse.jdt.ui/jdt-images/10.png | Bin 0 -> 226 bytes .../org.eclipse.jdt.ui/jdt-images/11.png | Bin 0 -> 438 bytes .../org.eclipse.jdt.ui/jdt-images/12.png | Bin 0 -> 436 bytes .../org.eclipse.jdt.ui/jdt-images/13.png | Bin 0 -> 490 bytes .../org.eclipse.jdt.ui/jdt-images/2.png | Bin 0 -> 281 bytes .../org.eclipse.jdt.ui/jdt-images/3.png | Bin 0 -> 228 bytes .../org.eclipse.jdt.ui/jdt-images/4.png | Bin 0 -> 105 bytes .../org.eclipse.jdt.ui/jdt-images/5.png | Bin 0 -> 509 bytes .../org.eclipse.jdt.ui/jdt-images/6.png | Bin 0 -> 487 bytes .../org.eclipse.jdt.ui/jdt-images/7.png | Bin 0 -> 238 bytes .../org.eclipse.jdt.ui/jdt-images/8.png | Bin 0 -> 277 bytes .../org.eclipse.jdt.ui/jdt-images/9.png | Bin 0 -> 194 bytes .../.workspace/2012/7/27/refactorings.history | 4 + .../.workspace/2012/7/27/refactorings.index | 1 + .../2012/6/26/refactorings.history | 3 + .../2012/6/26/refactorings.index | 3 + .../2012/7/27/refactorings.history | 3 + .../2012/7/27/refactorings.index | 2 + .../library/2012/7/27/refactorings.history | 3 + .../library/2012/7/27/refactorings.index | 15 + .../dialog_settings.xml | 11 + .../.cache/clean-cache.properties | 2 + .../org.eclipse.search/dialog_settings.xml | 175 + .../dialog_settings.xml | 5 + .../org.eclipse.ui.ide/dialog_settings.xml | 23 + .../dialog_settings.xml | 31 + .../dialog_settings.xml | 9 + .../org.eclipse.ui.workbench/workbench.xml | 592 ++++ .../org.eclipse.ui.workbench/workingsets.xml | 4 + .../dialog_settings.xml | 5 + .../default_catalog.xml | 5 + .../system_catalog.xml | 2 + .../dialog_settings.xml | 5 + .metadata/version.ini | 1 + .project | 33 + .../ActionBarSherlockCompat.java | 37 +- .../internal/app/ActionBarImpl.java | 7 +- example/AndroidManifest.xml | 1 + example/bin/classes.dex | Bin 692420 -> 689540 bytes example/bin/example.apk | Bin 599183 -> 571402 bytes example/bin/resources.ap_ | Bin 287967 -> 263572 bytes example/gen/com/actionbarsherlock/R.java | 373 +- example/gen/com/slidingmenu/example/R.java | 373 +- example/gen/com/slidingmenu/lib/R.java | 373 +- example/lint.xml | 3 + .../slidingmenu/example/ExampleActivity.java | 18 +- library/AndroidManifest.xml | 3 + library/gen/com/slidingmenu/lib/R.java | 357 +- library/res/layout/list.xml | 5 + library/res/layout/slidingmenumain.xml | 17 +- library/res/layout/slidingmenumainlist.xml | 7 + .../com/slidingmenu/lib/CustomViewAbove.java | 86 +- .../src/com/slidingmenu/lib/MenuScreen.java | 40 + .../src/com/slidingmenu/lib/SlidingMenu.java | 29 +- .../slidingmenu/lib/app/SlidingActivity.java | 41 +- .../lib/app/SlidingActivityBase.java | 22 + .../lib/app/SlidingFragmentActivity.java | 191 +- .../lib/app/SlidingListActivity.java | 193 +- .../lib/app/SlidingPreferenceActivity.java | 7 + 1096 files changed, 194063 insertions(+), 895 deletions(-) create mode 100644 .metadata/.lock create mode 100644 .metadata/.log create mode 100644 .metadata/.log-ajde create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabHost.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabWidget.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/preview.properties create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/AnalogClock.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/AutoCompleteTextView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Button.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/CalendarView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/CheckBox.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/CheckedTextView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Date.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/DigitalClock.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Email.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ExpandableListView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ImageButton.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ImageView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/LargeText.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ListView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MediumText.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultiAutoCompleteTextView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultilineText.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Number.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/NumberDecimal.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/NumberSigned.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Password.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PasswordNumeric.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PersonName.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Phone.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PlainText.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PostalAddress.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarHorizontal.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarLarge.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarNormal.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarSmall.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/QuickContactBadge.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RadioButton.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RadioGroup.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RatingBar.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/SeekBar.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/SmallButton.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/SmallText.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Spinner.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Switch.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/TabHost.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/TabWidget.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/TextView.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Time.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ToggleButton.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ZoomButton.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ZoomControls.png create mode 100644 .metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/preview.properties create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/0/4064100f09c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/0/60866c2216c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/0/a05891ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1/124c97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1/408c8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1/43fd8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1/91a293ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/10/0060e76d24c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/10/10660e4d1ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/10/800a91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/11/308173515bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/11/600d2b0d54c3001115d2d454e05194c5 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/11/90cb999352c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/11/c07980e02ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/11/e1128dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/12/9062a79e52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/12/b1f093ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/13/00abe03af4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/13/01618dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/13/50ab3dce27c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/13/72e390ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/14/02618dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/14/11db94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/14/d0475e0416c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/034392ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/108247f025c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/10e44a7c48c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/5049ccb55bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/a35891ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/f095f093f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/15/f0aa8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/16/106a92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/16/40b72d9993c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/42df92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/a1e78eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/b17f91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/c0ffac6d5bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/d1af96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/f11b92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/17/f1fd96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/18/53248eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/18/b0e0d3895bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/18/d0b0605522c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1a/0080b4134dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1a/4007eefdf5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1a/d0092b01f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1b/735493ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1b/d086255424c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1c/305e0e93f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1c/90be36fe0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1d/223e8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1d/51248eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1d/72018cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1e/319a97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1e/70f3e032f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1e/f0398dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1f/c0845dea21c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/1f/e1d696ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2/10d077ea0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2/20946fb921c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2/8099fbcc26c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/20/02b494ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/21/30341a1d1dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/22/807e73955bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/22/810a91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/22/a03a96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/22/e3f491ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/23/60ed698bf5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/23/b49d8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/23/c0e555472ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/23/f3398dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/24/729089ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/24/82b789ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/24/c0df82c992c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/24/e2a18aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/24/f0f870e429c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/25/749089ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/26/519590ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/26/e048c3922ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/27/01b494ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/27/6033c5f323c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/27/609ea3ecf9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/31658bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/70057c8e2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/911396ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/b27f91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/f0f29cfff9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/28/f3aa8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/29/30090a0115c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/29/616989ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/29/905af89f29c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2a/418c8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2a/8022e93b50c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2a/a02e166910c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/107967b493c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/309ba40953c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/609e95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/80de661d26c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/934f8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/c04155c62ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/d04376d3f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/d08076ac92c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2b/e0ba844116c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2d/b2f093ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2e/2054ee332cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2e/c1538aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2f/10c93c565bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2f/8044d37d16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/2f/80ef8a9d25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3/404300032bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3/43c197ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3/70780f1425c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3/70a23da324c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/30/53e897ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/30/f1aa8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/31/1068dc514ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/002597ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/100aca332bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/200295ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/72c595ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/e07423b75bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/e16594ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/f01b92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/32/f0fd96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/33/74c595ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/33/82998eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/34/8050194127c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/34/a0909ce4f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/34/f2c88aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/20cb185852c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/302995ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/31d68dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/51e897ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/7041672c50c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/35/80e1c04311c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/36/b05c60f4f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/36/b0ac19ae25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/36/d1cd91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/36/e0fab3fc27c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/37/00bd789329c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/37/210295ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/37/30f5e4251fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/37/c0b4cd8144c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/37/c0b7cddb14c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/39/405b522352c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/39/70c4716c0ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/39/a2058aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/39/c3358fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/20041b1c53c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/31b892ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/504289ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/52b38bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/600f98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3a/c057f0272ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3b/c0a56ae184c2001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3b/f1398dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3c/322995ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3c/b0dc31fa4fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3d/40770b6e0ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3e/006a1cff14c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3e/1022dd1016c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3e/500693ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3e/700c792750c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3f/20eabc0b93c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3f/40f359ee30c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3f/a0caf7e90cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/3f/b0be286bf4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4/503515422ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4/b0eb29d9f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/40/506bf92f31c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/40/506e84b029c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/40/71e390ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/40/b03079d925c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/41/90537ff530c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/42/34d68dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/42/510693ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/42/a3c993ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/106cb88024c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/222090ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/706aa73126c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/83998eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/901e4c3952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/43/d0c39f1928c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/30b3a98848c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/70ea366f24c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/804e638329c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/80cb36334ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/b0588f1a1fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/c06fc2145cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/44/e0a5eacfa4c300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/45/20b4917e27c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/45/e0dd634f15c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/201b429ff3c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/514289ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/6020896ef7c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/80cdb0cc29c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/a009563952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/d011a3300dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/46/e00ee88e48c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/47/530693ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/47/70e189435dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/47/b26196ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/48/44c197ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/48/d0174c80f7c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/00618dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/304ca72952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/50e897ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/6097013231c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/80dcec090bc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/c00e33f230c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/49/f0f4be3226c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4a/60fc8a4d5bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4b/504468fa23c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4b/606d4ce884c2001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4b/a07587ab10c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4c/619e95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4c/620f98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4c/70f65436f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4d/12f98fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4d/201c87f327c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4d/34b892ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4d/50f3542352c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/004e4e77f7c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/506ad73d16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/506d569e5bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/606989ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/71018cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/4e/c070ce372ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5/6058c6e993c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5/90b142b93ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/50/329a97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/50/608eddae95c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/50/90c36dfe4dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/50/b00e8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/51/00ff810724c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/51/20a7fa5929c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/51/41df92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/51/91de89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/51/c0cc6f3315c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/52/701959d429c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/52/b067091b40c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/004392ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/22af8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/70acb12952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/73018cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/80ffd98a2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/c21794ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/53/e0a18aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/54/827b93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/54/83b789ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/54/e0eb28575dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/54/f0e8df4316c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/55/54248eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/55/725493ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/55/d1eb8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/56/907ef79c24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/56/b057160f09c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/56/f0f618e311c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/00128e7e24c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/201b61def9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/a0c993ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/b033f63c27c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/c2a691ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/57/e018401d24c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/58/30edfe7f0dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/58/a2e78eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/59/309a97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/59/609c1e6e52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/59/a015408c93c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/59/c069972b0dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/59/d07a8aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5a/509590ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5a/91c08eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5a/b0771c5529c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5b/108dfe1115c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5b/40fd0505fac500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5b/b30e8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5c/4018fb3525c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5c/c0538aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5d/60b6984915c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5d/610f98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5d/815d98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5e/c06fde164dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/5f/f04cf1390ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6/715493ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6/83288cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6/c2538aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6/e0bc80581fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/60/146a92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/60/a3768cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/60/b39d8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/50248eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/703698ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/70598081f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/71c595ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/913191ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/61/e0548665f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/62/601a552352c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/62/7015e02226c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/62/c038db3c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/62/c05b8a4653c3001115d2d454e05194c5 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/63/007dfa8d29c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/63/13888dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/63/9020d055f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/63/e092273052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/63/f053d17c0dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/64/306e50a72ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/64/435095ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/64/6037a5b016c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/64/904f8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/64/e053992f16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/65/20c526055cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/65/a4058aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/65/d27a8aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/66/32658bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/66/d09cd4b552c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/67/12888dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/67/30a36c71f5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/67/404991cd28c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/67/70b352830ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/67/e029c91e24c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/68/012597ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/68/924f8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/69/50de51fe25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/69/601e89202cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/69/90053b045cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/69/d13e94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/69/e0243f142ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6a/04618dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6a/10178bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6a/217397ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6a/739089ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6b/b09d8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6b/e0d18a5724c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6c/428c8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6c/94c08eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6d/b0e576ea0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6d/d0b95e3e26c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6e/9038117b2ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6e/e0a5563952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/022597ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/207397ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/300b9f5a2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/30658bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/506c78ea0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/805d98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/6f/9054a9832ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/70/044392ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/71/10e222d4f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/71/507795ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/71/d37a8aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/30d68dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/312995ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/406170bff8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/60a4603816c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/a0cf768d1cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/72/e04c6b0426c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/74/00e1273052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/74/032597ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/74/32b892ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/74/a08e698a27c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/75/002e00504ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/75/a0768cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/75/e0e81e9144c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/11178bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/20560baaf3c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/702831bf52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/82288cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/a1058aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/c0ea58865bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/76/e1838fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/77/719089ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/78/1098152e2cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/78/a0a5d5fb94c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/78/b16196ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/78/f0c6d0d2f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/79/9058251f40c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7a/40df92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7a/70728eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/219192ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/308b22fbf5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/32d68dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/4016ef4f2bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/a0c8141b5cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/c11794ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/e3a18aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7b/f28c94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7c/73c595ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7c/c09972fa50c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7c/e0fc70511ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7d/00b494ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7d/30b892ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7d/54e897ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7d/e2f491ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7e/209192ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7f/20bdc373f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7f/82ec95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7f/c1a691ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/7f/e0a11e2393c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8/0094c70a2ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8/10db94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8/537795ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/529590ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/604f8e870cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/84288cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/92de89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/d17a8aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/80/f0a05d91f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/82/201c6ecf52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/82/20df03185cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/82/448c8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/82/e1a18aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/83/009102e229c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/83/5085db29f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/83/6007dfe223c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/83/f21b92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/83/f2fd96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/84/622d93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/84/a4c993ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/85/4094b6c125c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/85/f0c88aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/108d5a6d26c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/20f6d7cd2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/33b892ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/421b89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/80288cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/86/e4a18aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/87/10efd0432ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/87/324790ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/87/415095ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/87/90c08eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/87/c4358fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/88/00dac57f48c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/88/01f08aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/88/723698ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/89/33d68dff24c3001119baa706e9d70c26 create mode 100755 .metadata/.plugins/org.eclipse.core.resources/.history/89/70f2283052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/89/743698ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/89/907a82e930c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/89/b0f093ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/89/d0305c4a3ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8a/11888dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8a/40355f4f5dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8a/c0af62282ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8a/f0127fde52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8b/0048e819f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8b/23af8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8b/606e710d16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8b/92c08eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8b/f01075ea0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/200b8dcc24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/61bc90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/70d9149024c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/90de89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/b07f91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/d0c20e8af8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8c/d0eb8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8d/30f44a092cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8d/9007c34315c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8e/304790ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8e/50e172181fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8e/90126ef42bc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8f/02f08aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8f/426e90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8f/80ec95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8f/a25891ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/8f/f05f6a694ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/014392ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/2073b0f72ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/305425242ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/507ec6064fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/60759eacf9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9/c01794ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/90/b02c8aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/90/f093d2de30c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/91/40c38c6824c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/91/40d25635f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/91/e0f09c4a1ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/3047871c16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/50d573254ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/52e897ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/72728eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/c05cdb825bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/93/c0d88cd2f9c500111689feaa37e8ab14 create mode 100755 .metadata/.plugins/org.eclipse.core.resources/.history/94/00f4563952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/03f08aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/33658bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/6068e9cdf9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/63bc90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/a0e09e241fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/94/e26594ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/95/309ee17f2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/95/612d93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/95/d0c5554c5dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/95/e064c92585c2001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/95/e0c8be1d2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/96/10888dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/96/2003e8bc4fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/96/817b93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/96/90657c4f2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/97/a1c993ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/98/30a5542352c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/002bb3562ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/1089edc6f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/108c455540c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/53b38bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/9018d253f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/c06a7fed0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/c09f2a102bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/99/f024649ef8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9a/400a60aef3c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9a/4044c7f125c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9b/12178bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9b/203b390e2ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9b/232090ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9b/40ec4cc82bc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9b/b07c0ee491c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9c/51b38bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9c/805daa0f0dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9c/9094f77227c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9c/c0a415382ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9d/3040e8d714c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9d/62bc90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9e/60da8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9e/a0ad00d7f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9e/e03197db29c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9f/13178bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9f/7021b3484ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9f/825d98ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/9f/c28896ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a/116a92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a/5055944bf4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a/e0f491ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a0/11f98fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a0/f02ff42df6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a0/f1c88aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a2/10336a830ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a2/339a97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a2/60ecce2f22c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a3/a3058aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a4/42fd8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a4/807b93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a4/f06925abf9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a4/f2aa8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a5/70da467615c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a5/8080ed4ef6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a5/c04c6a0226c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a6/42c197ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a7/b0ef28552ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a7/e0838fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a7/e086db3c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a8/c03c2a545bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a9/207a7344fac500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a9/30af1c540ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/a9/c0215a9316c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/aa/40e1d7525dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ab/202090ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ab/403eb6a027c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ab/527795ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ac/304e556d2cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ac/405095ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ad/90135f3f49c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ad/c0155d284ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ae/212090ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/af/f2398dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/20bac3355dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/60662a0d2ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/923191ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/b0d2f59752c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/d03e94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b0/d2eb8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b1/300e77481fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b1/604b8eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b1/7005ba380ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b1/f00258ec26c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b2/10348a342ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b2/43df92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b2/b0551c03fac500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b2/c1c48cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b3/40481c3052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b4/81288cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b4/c0358fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b4/c0b1d4870dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b5/00a545fd52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b5/8042022029c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b5/a1768cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/00d28fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/1020ba2b25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/24af8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/80379b1b2cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/a0058aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b6/a0e3b66df4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b7/c18896ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b7/e2128dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b8/90aa1d6f0ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b8/f0543b872ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b8/f3c88aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b9/805477ca27c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b9/914f8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b9/e06a3a3c10c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/b9/e2d696ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ba/2002f03b15c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ba/931396ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bb/20af8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bb/20d7532a16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bb/52248eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bc/10f98fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bc/705493ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bc/903191ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bc/e002f968f3c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bd/308e08963dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bd/804a8bb591c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bd/81ec95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/be/00b9f6452cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/be/21af8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/be/a04a6a8e0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bf/7021a05c25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bf/807c6b3949c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bf/9021e1b05bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bf/90b3badcf8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/bf/e0d01f1995c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/102a1f3c26c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/4023f514f3c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/40afb916f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/411b89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/71728eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/9040293052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/a15891ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/c0c48cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c0/e0128dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c1/425095ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c1/7013a1ff4dc3001119baa706e9d70c26 create mode 100755 .metadata/.plugins/org.eclipse.core.resources/.history/c1/c057563952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c2/10bda06a4ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c2/a3e78eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c3/106dde3c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c3/80998eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c3/80b442fd23c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c3/93de89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c4/70208f3228c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c5/233e8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c5/c08896ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c5/d049ec4e4ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c6/70c1ac002ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c6/733698ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c6/c1358fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c7/005090eef5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c7/624b8eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c7/d3cd91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c7/f0b942944bc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c8/9038a7ce24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c8/93c08eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c9/314790ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c9/40fd8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c9/416e90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c9/438c8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/c9/b07438830ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ca/20a5994249c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ca/90aabe775bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ca/f08c94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cb/102615a1f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cb/40c197ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cb/9018bc4f2cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cb/b10e8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cc/4059872d15c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cc/406d95885bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cc/e0bdb22952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cd/202ecd5df6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cd/709089ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cd/80e5b6db42c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cd/c0c9d4312bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/00ae1d4746c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/1084ff275cc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/332995ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/60fc548c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/634b8eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/d0af96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ce/e0d696ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cf/706fcb505dc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cf/a05215462ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cf/b29d8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/cf/d01a23110dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d/50bd96002bc500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d/517795ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d/60473271f7c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d/c0a691ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d0/005d1d5f52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d0/92a293ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d0/d06f13f90cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d1/10443768f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d1/10ee022a31c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d1/406b197ef5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d1/c3538aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d2/00f08aff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d2/7099c78429c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d3/0075e3221fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d3/b0f8be0224c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d3/d2cd91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d4/80b789ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d5/c047458a2ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d6/60c50ddd23c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d6/614b8eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d6/b000bdac16c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d7/a0e78eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d8/90b213a8f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d8/a2c993ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/d9/e0175dd428c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/da/20cc06314ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/da/709dc68093c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/db/70c595ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/db/713698ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/db/e1f491ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dc/10ab82973dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dc/90a293ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dc/c0f743ac95c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dc/f06061c914c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dd/73728eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/dd/800dc70c2ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/de/30efe0e725c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/df/204547f6f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/df/d0fccccff6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/df/e00126e023c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e/024392ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/204a863e25c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/41c197ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/509cd0de29c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/50b38bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/524289ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/80b3233a4ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e0/820a91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e1/00d96a71f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e1/63da8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e1/70e088d829c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/406e90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/41fd8dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/50a4283052c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/60a7b2caf9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/a13a96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e2/b04834e62ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e3/136a92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e3/b06196ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e3/e06594ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e3/e0f3201785c2001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e4/10e6ec4e4ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e4/520693ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e4/70d9e47415c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e4/805d61b9f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e5/20c2ed1b1dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e5/20d4b2be28c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e5/70ada704f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e6/81b789ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e6/d3af96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e7/126a92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e7/f07cf8c726c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e8/20a470ea0cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e8/62da8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e8/d06d700253c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e8/e3128dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/e9/90fd3c83f4c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/eb/02d28fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/eb/401b89ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/eb/60bc90ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/eb/803c9c0328c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ec/01d28fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ec/114c97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ec/f01dc6bbf8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ed/90be72830ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ed/d01e0b5415c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ee/c2358fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ef/101b573952c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ef/10a7ac4b2ac500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ef/60b92661f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ef/d0cd91ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ef/f18c94ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/0046de3c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/03618dff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/2001a1f3f5c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/83ec95ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/908498ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f/f31b92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/104c97ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/213e8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/40f1ff8d26c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/801e582a27c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/b042b8554ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/b19d8cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/d022329526c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f0/d075347f50c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f1/81998eff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f2/602d93ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f2/d2af96ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f3/008829b329c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f3/2094de3c52c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f3/407cadf691c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f3/60cf24294ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f3/a0ea34e4f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f4/70018cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f4/80386628f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f4/b20e8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f5/00717c57f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f5/203e8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f5/2072c80454c3001115d2d454e05194c5 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f5/901396ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f6/002ffafc50c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f6/00e68715f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f6/90abdc014ec3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f7/50c9c9910cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f7/e0b5afb7f9c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f7/f0ec1f0e0dc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f8/11e6ec4e4ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f8/5067ce9f5bc300111ab8b17b137f3789 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f8/d0cef5e90cc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f9/44df92ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f9/61da8bff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f9/921396ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/f9/a005ca4d26c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fa/004a499242c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fa/70e390ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fa/a2768cff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fb/209cea4e4ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fc/9080fd0f4fc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fc/f0d090c514c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fd/30f488ff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fd/5056cd32f6c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fd/50c1c6d325c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fd/804c0dfe2bc3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fd/d0f3e8b693c500111b2a8b7f47e59881 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fe/b029bb50f8c500111689feaa37e8ab14 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fe/d05c8fff24c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/fe/e09b7f8424c3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ff/109445830ac3001119baa706e9d70c26 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.history/ff/40d5f01c54c3001115d2d454e05194c5 create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/30/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/32/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/3a/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/4a/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/54/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/62/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/63/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/67/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/77/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/81/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/93/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/cb/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/cd/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d6/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d8/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/e/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/eb/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/ee/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/f6/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/fa/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/92/81/a/bd/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/30/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/32/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/3a/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/3c/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/4a/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/54/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/61/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/62/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/63/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/67/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/77/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/81/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/82/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/93/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/cb/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/cd/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d6/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d8/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/de/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/e/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/eb/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/ee/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/f6/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/fa/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/21/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/a5/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bc/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/84/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/84/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/bc/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/21/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/a5/5f/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/a5/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/bc/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/21/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/21/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/a5/5f/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/bc/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.syncinfo.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/d6/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/de/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/e4/81/73/96/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.markers create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.markers.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/example/.syncinfo.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/3c/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/3d/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/5f/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/61/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/62/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/82/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/d6/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/d6/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/de/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/de/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/f3/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/1d/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/21/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/history.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.markers create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.markers.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.projects/library/.syncinfo.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.markers create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.markers.snap create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/4.tree create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.snap create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.adt.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.ddms.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/net.rim.ajde.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.debug.ui.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.search.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.browser.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.core.prefs create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.ui.prefs create mode 100644 .metadata/.plugins/org.eclipse.debug.core/.launches/example.launch create mode 100644 .metadata/.plugins/org.eclipse.debug.ui/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.debug.ui/launchConfigurationHistory.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/1440040889.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/1577419489.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/1717276877.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/1809425343.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/2040064081.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/2240772384.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/2942843900.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/3058661946.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/3069504370.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/4000112963.index create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/invalidArchivesCache create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt create mode 100644 .metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat create mode 100644 .metadata/.plugins/org.eclipse.jdt.debug.ui/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.launching/.install.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.launching/libraryInfos.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/0.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/1.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/10.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/11.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/12.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/13.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/2.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/3.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/4.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/5.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/6.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/7.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/8.png create mode 100644 .metadata/.plugins/org.eclipse.jdt.ui/jdt-images/9.png create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/7/27/refactorings.history create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/7/27/refactorings.index create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/ActionBarSherlockSlidingMenu/2012/6/26/refactorings.history create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/ActionBarSherlockSlidingMenu/2012/6/26/refactorings.index create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/ActionBarSherlockSlidingMenu/2012/7/27/refactorings.history create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/ActionBarSherlockSlidingMenu/2012/7/27/refactorings.index create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/library/2012/7/27/refactorings.history create mode 100644 .metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/library/2012/7/27/refactorings.index create mode 100644 .metadata/.plugins/org.eclipse.ltk.ui.refactoring/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.pde.core/.cache/clean-cache.properties create mode 100644 .metadata/.plugins/org.eclipse.search/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.editors/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.workbench.texteditor/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.workbench/workbench.xml create mode 100644 .metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml create mode 100644 .metadata/.plugins/org.eclipse.wst.sse.ui/dialog_settings.xml create mode 100644 .metadata/.plugins/org.eclipse.wst.xml.core/default_catalog.xml create mode 100644 .metadata/.plugins/org.eclipse.wst.xml.core/system_catalog.xml create mode 100644 .metadata/.plugins/org.eclipse.wst.xml.ui/dialog_settings.xml create mode 100644 .metadata/version.ini create mode 100644 .project create mode 100644 example/lint.xml create mode 100644 library/res/layout/list.xml create mode 100644 library/res/layout/slidingmenumainlist.xml create mode 100644 library/src/com/slidingmenu/lib/MenuScreen.java create mode 100644 library/src/com/slidingmenu/lib/app/SlidingActivityBase.java create mode 100644 library/src/com/slidingmenu/lib/app/SlidingPreferenceActivity.java diff --git a/.metadata/.lock b/.metadata/.lock new file mode 100644 index 000000000..e69de29bb diff --git a/.metadata/.log b/.metadata/.log new file mode 100644 index 000000000..9e51bc17b --- /dev/null +++ b/.metadata/.log @@ -0,0 +1,3057 @@ +!SESSION 2012-06-29 22:28:41.307 ----------------------------------------------- +eclipse.buildId=M20120208-0800 +java.version=1.6.0_24 +java.vendor=Sun Microsystems Inc. +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US +Command-line arguments: -data /home/jeremy/workspace/SlidingMenu/SlidingMenu -os linux -ws gtk -arch x86_64 + +!ENTRY org.eclipse.osgi 2 1 2012-06-29 22:28:47.614 +!MESSAGE NLS unused message: Preference_Empty_SSH_Path_Msg in: net.rim.ajde.internal.messages.messages + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-29 22:29:33.091 +!MESSAGE +!STACK 1 +org.eclipse.core.internal.resources.ResourceException: Resource '/library/res' does not exist. + at org.eclipse.core.internal.resources.Resource.checkExists(Resource.java:320) + at org.eclipse.core.internal.resources.Resource.checkAccessible(Resource.java:194) + at org.eclipse.core.internal.resources.Container.members(Container.java:266) + at org.eclipse.core.internal.resources.Container.members(Container.java:249) + at com.android.ide.eclipse.adt.internal.sdk.Sdk$6.run(Sdk.java:1302) + at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) +!SUBENTRY 1 org.eclipse.core.resources 4 368 2012-06-29 22:29:33.092 +!MESSAGE Resource '/library/res' does not exist. + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-29 22:29:45.605 +!MESSAGE +!STACK 1 +org.eclipse.core.internal.resources.ResourceException: Resource '/example/res' does not exist. + at org.eclipse.core.internal.resources.Resource.checkExists(Resource.java:320) + at org.eclipse.core.internal.resources.Resource.checkAccessible(Resource.java:194) + at org.eclipse.core.internal.resources.Container.members(Container.java:266) + at org.eclipse.core.internal.resources.Container.members(Container.java:249) + at com.android.ide.eclipse.adt.internal.sdk.Sdk$6.run(Sdk.java:1302) + at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) +!SUBENTRY 1 org.eclipse.core.resources 4 368 2012-06-29 22:29:45.605 +!MESSAGE Resource '/example/res' does not exist. + +!ENTRY org.eclipse.ui 4 4 2012-06-29 22:29:50.795 +!MESSAGE Invalid preference page path: XML Syntax + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 15:45:26.245 +!MESSAGE +!STACK 1 +org.eclipse.core.internal.resources.ResourceException: Resource '/ActionBarSherlock2/res' does not exist. + at org.eclipse.core.internal.resources.Resource.checkExists(Resource.java:320) + at org.eclipse.core.internal.resources.Resource.checkAccessible(Resource.java:194) + at org.eclipse.core.internal.resources.Container.members(Container.java:266) + at org.eclipse.core.internal.resources.Container.members(Container.java:249) + at com.android.ide.eclipse.adt.internal.sdk.Sdk$6.run(Sdk.java:1302) + at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) +!SUBENTRY 1 org.eclipse.core.resources 4 368 2012-06-30 15:45:26.245 +!MESSAGE Resource '/ActionBarSherlock2/res' does not exist. + +!ENTRY org.eclipse.ui 4 4 2012-06-30 16:34:37.401 +!MESSAGE Referenced part does not exist yet: org.eclipse.ui.views.ProblemView. + +!ENTRY org.eclipse.ui 4 0 2012-06-30 16:44:36.139 +!MESSAGE Unhandled event loop exception +!STACK 0 +org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.core.runtime.AssertionFailedException: null argument:) + at org.eclipse.swt.SWT.error(SWT.java:4282) + at org.eclipse.swt.SWT.error(SWT.java:4197) + at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:138) + at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) +Caused by: org.eclipse.core.runtime.AssertionFailedException: null argument: + at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:85) + at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:73) + at org.eclipse.jface.viewers.StructuredViewer.assertElementsNotNull(StructuredViewer.java:599) + at org.eclipse.jface.viewers.StructuredViewer.getRawChildren(StructuredViewer.java:1011) + at org.eclipse.jface.viewers.ColumnViewer.getRawChildren(ColumnViewer.java:703) + at org.eclipse.jface.viewers.AbstractTableViewer.getRawChildren(AbstractTableViewer.java:1087) + at org.eclipse.jface.viewers.StructuredViewer.getFilteredChildren(StructuredViewer.java:917) + at org.eclipse.jface.viewers.StructuredViewer.getSortedChildren(StructuredViewer.java:1067) + at org.eclipse.jface.viewers.AbstractTableViewer.internalVirtualRefreshAll(AbstractTableViewer.java:676) + at org.eclipse.jface.viewers.AbstractTableViewer.internalRefresh(AbstractTableViewer.java:651) + at org.eclipse.jface.viewers.AbstractTableViewer.internalRefresh(AbstractTableViewer.java:636) + at org.eclipse.jface.viewers.StructuredViewer$7.run(StructuredViewer.java:1508) + at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1443) + at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1404) + at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1506) + at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:537) + at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1465) + at com.android.ddmuilib.logcat.LogCatPanel$LogCatTableRefresherTask.run(LogCatPanel.java:1093) + at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35) + at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135) + ... 23 more + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 16:53:00.794 +!MESSAGE Failed to call IFileListener.fileChanged +!STACK 0 +java.lang.StackOverflowError + at java.util.Collections.unmodifiableList(Collections.java:1149) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.getLibraries(ProjectState.java:318) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:650) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.buildFullLibraryDependencies(ProjectState.java:653) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 16:53:23.004 +!MESSAGE Failed to call IResourceEventListener.resourceChangeEventEnd +!STACK 0 +java.lang.StackOverflowError + at java.util.Collections.unmodifiableList(Collections.java:1149) + at com.android.ide.eclipse.adt.internal.sdk.ProjectState.getParentProjects(ProjectState.java:549) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1231) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + at com.android.ide.eclipse.adt.internal.sdk.Sdk.updateParentProjects(Sdk.java:1242) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 17:01:54.883 +!MESSAGE Error while loading editor +!STACK 0 +java.lang.NullPointerException + at com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationComposite.onXmlModelLoaded(ConfigurationComposite.java:691) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.onTargetChange(GraphicalEditorPart.java:1014) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.onDescriptorsChanged(LayoutEditorDelegate.java:652) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateInitUiRootNode(LayoutEditorDelegate.java:574) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateXmlModelChanged(LayoutEditorDelegate.java:347) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.xmlModelChanged(CommonXmlEditor.java:327) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor$XmlModelStateListener.modelChanged(AndroidXmlEditor.java:1569) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createTextEditor(AndroidXmlEditor.java:781) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createAndroidPages(AndroidXmlEditor.java:294) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:284) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) + at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) + at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) + at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) + at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) + at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) + at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) + at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) + at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) + at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) + at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) + at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) + at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) + at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) + at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) + at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) + at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) + at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) + at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 19:26:10.717 +!MESSAGE Error while loading editor +!STACK 0 +java.lang.NullPointerException + at com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationComposite.onXmlModelLoaded(ConfigurationComposite.java:691) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.onTargetChange(GraphicalEditorPart.java:1014) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.onDescriptorsChanged(LayoutEditorDelegate.java:652) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateInitUiRootNode(LayoutEditorDelegate.java:574) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateXmlModelChanged(LayoutEditorDelegate.java:347) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.xmlModelChanged(CommonXmlEditor.java:327) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor$XmlModelStateListener.modelChanged(AndroidXmlEditor.java:1569) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createTextEditor(AndroidXmlEditor.java:781) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createAndroidPages(AndroidXmlEditor.java:294) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:284) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) + at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) + at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) + at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) + at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) + at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) + at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) + at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) + at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) + at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) + at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) + at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) + at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) + at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) + at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) + at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) + at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) + at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) + at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-06-30 19:26:24.780 +!MESSAGE Error while loading editor +!STACK 0 +java.lang.NullPointerException + at com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationComposite.onXmlModelLoaded(ConfigurationComposite.java:691) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.onTargetChange(GraphicalEditorPart.java:1014) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.onDescriptorsChanged(LayoutEditorDelegate.java:652) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateInitUiRootNode(LayoutEditorDelegate.java:574) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateXmlModelChanged(LayoutEditorDelegate.java:347) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.xmlModelChanged(CommonXmlEditor.java:327) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor$XmlModelStateListener.modelChanged(AndroidXmlEditor.java:1569) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createTextEditor(AndroidXmlEditor.java:781) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createAndroidPages(AndroidXmlEditor.java:294) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:284) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) + at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) + at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) + at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) + at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) + at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) + at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) + at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) + at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) + at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) + at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) + at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) + at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) + at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) + at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) + at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) + at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) + at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) + at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) + +!ENTRY org.eclipse.core.jobs 4 2 2012-07-01 00:00:13.123 +!MESSAGE An internal error occurred during: "Android Library Update". +!STACK 0 +java.lang.NullPointerException + at com.android.ide.eclipse.adt.internal.project.LibraryClasspathContainerInitializer.allocateLibraryContainer(LibraryClasspathContainerInitializer.java:187) + at com.android.ide.eclipse.adt.internal.project.LibraryClasspathContainerInitializer.updateProjects(LibraryClasspathContainerInitializer.java:69) + at com.android.ide.eclipse.adt.internal.sdk.Sdk$3$1.run(Sdk.java:1192) + at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 00:00:16.065 +!MESSAGE Unknown error: java.lang.NullPointerException +!STACK 0 +java.lang.NullPointerException + at com.android.ide.eclipse.adt.internal.build.BuildHelper.handleClasspathLibrary(BuildHelper.java:981) + at com.android.ide.eclipse.adt.internal.build.BuildHelper.handleCPE(BuildHelper.java:932) + at com.android.ide.eclipse.adt.internal.build.BuildHelper.handleCPE(BuildHelper.java:943) + at com.android.ide.eclipse.adt.internal.build.BuildHelper.gatherPaths(BuildHelper.java:898) + at com.android.ide.eclipse.adt.internal.build.BuildHelper.(BuildHelper.java:142) + at com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.build(PostCompilerBuilder.java:429) + at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:728) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:199) + at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:239) + at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:292) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:295) + at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:351) + at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:374) + at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:143) + at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:241) + at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) +!SESSION 2012-07-01 01:03:08.496 ----------------------------------------------- +eclipse.buildId=M20120208-0800 +java.version=1.6.0_24 +java.vendor=Sun Microsystems Inc. +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US +Command-line arguments: -os linux -ws gtk -arch x86_64 + +!ENTRY org.eclipse.osgi 2 1 2012-07-01 01:03:23.966 +!MESSAGE NLS unused message: Preference_Empty_SSH_Path_Msg in: net.rim.ajde.internal.messages.messages + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.092 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.099 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.100 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.122 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.144 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.144 +!MESSAGE palette: Failed to find style 'autoCompleteTextViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.147 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.148 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.148 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.151 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.152 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.153 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.153 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.154 +!MESSAGE palette: Failed to find style 'buttonStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.159 +!MESSAGE palette: Failed to find style 'checkboxStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.160 +!MESSAGE palette: Failed to find style 'checkboxStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.161 +!MESSAGE palette: Failed to find style 'checkboxStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.162 +!MESSAGE palette: Failed to find style 'checkboxStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.163 +!MESSAGE palette: Failed to find style 'checkboxStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.170 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.170 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.171 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.171 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.236 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.237 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.237 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.238 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.238 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.239 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.239 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.245 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.246 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.246 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.247 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.247 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.248 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.248 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.248 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.249 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.250 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.250 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.251 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.252 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.252 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.253 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.253 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.253 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.254 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.254 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.255 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.255 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.256 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.256 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.256 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.257 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.258 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.258 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.258 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.259 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.260 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.260 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.261 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.261 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.262 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.262 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.262 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.263 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.264 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.265 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.265 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.266 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.266 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.267 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.267 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.267 +!MESSAGE palette: Failed to find style 'editTextStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.268 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.269 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.282 +!MESSAGE Failed to render set of icons for AnalogClock, AutoCompleteTextView, Button, SmallButton, CheckBox, CheckedTextView, DigitalClock, PlainText, Password, PasswordNumeric, PersonName, Phone, PostalAddress, MultilineText, Date, Time, Email, Number, NumberSigned, NumberDecimal, LargeText, MediumText, SmallText, ImageButton, ImageView, MultiAutoCompleteTextView, ProgressBarNormal, ProgressBarHorizontal, ProgressBarLarge, ProgressBarSmall, QuickContactBadge, RadioButton, RatingBar, SeekBar, ListView, ExpandableListView, Spinner, TextView, ToggleButton, ZoomButton, ZoomControls, CalendarView, RadioGroup + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.282 +!MESSAGE +!STACK 0 +android.content.res.Resources$NotFoundException + at com.android.layoutlib.bridge.android.BridgeContext.obtainStyledAttributes(BridgeContext.java:450) + at android.content.res.Resources_Theme_Delegate.obtainStyledAttributes(Resources_Theme_Delegate.java:48) + at android.content.res.Resources$Theme.obtainStyledAttributes(Resources.java:1174) + at android.widget.TextView.(TextView.java:493) + at android.widget.TextView.(TextView.java:442) + at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) + at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) + at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) + at java.lang.reflect.Constructor.newInstance(Constructor.java:532) + at android.view.LayoutInflater.createView(LayoutInflater.java:586) + at android.view.BridgeInflater.onCreateView(BridgeInflater.java:86) + at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653) + at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678) + at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:131) + at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:739) + at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64) + at android.view.LayoutInflater.rInflate(LayoutInflater.java:711) + at android.view.LayoutInflater.inflate(LayoutInflater.java:489) + at android.view.LayoutInflater.inflate(LayoutInflater.java:372) + at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:321) + at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:324) + at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService.createRenderSession(RenderService.java:372) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.render(PreviewIconFactory.java:271) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.initColors(PreviewIconFactory.java:579) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.getBackgroundColor(PreviewIconFactory.java:554) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PaletteControl.reloadPalette(PaletteControl.java:425) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.reloadPalette(GraphicalEditorPart.java:1128) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart$ConfigListener.onConfigurationChange(GraphicalEditorPart.java:524) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.onTargetChange(GraphicalEditorPart.java:1017) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.onDescriptorsChanged(LayoutEditorDelegate.java:652) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateInitUiRootNode(LayoutEditorDelegate.java:574) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateXmlModelChanged(LayoutEditorDelegate.java:347) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.xmlModelChanged(CommonXmlEditor.java:327) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor$XmlModelStateListener.modelChanged(AndroidXmlEditor.java:1569) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createTextEditor(AndroidXmlEditor.java:781) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createAndroidPages(AndroidXmlEditor.java:294) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:284) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) + at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) + at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) + at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) + at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) + at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) + at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) + at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) + at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) + at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) + at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) + at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) + at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) + at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) + at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) + at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) + at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) + at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) + at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.287 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.287 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.288 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.288 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.288 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.292 +!MESSAGE palette: Failed to find style 'switchStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.300 +!MESSAGE Failed to render set of icons for Switch + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.301 +!MESSAGE +!STACK 0 +java.lang.NullPointerException + at android.widget.Switch.jumpDrawablesToCurrentState(Switch.java:651) + at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:5030) + at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:5030) + at android.widget.FrameLayout.jumpDrawablesToCurrentState(FrameLayout.java:172) + at android.view.View.onAttachedToWindow(View.java:9537) + at android.view.View.dispatchAttachedToWindow(View.java:9784) + at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2198) + at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:37) + at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:329) + at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:324) + at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService.createRenderSession(RenderService.java:372) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.render(PreviewIconFactory.java:271) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.initColors(PreviewIconFactory.java:579) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PreviewIconFactory.getBackgroundColor(PreviewIconFactory.java:554) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.PaletteControl.reloadPalette(PaletteControl.java:425) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.reloadPalette(GraphicalEditorPart.java:1128) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart$ConfigListener.onConfigurationChange(GraphicalEditorPart.java:524) + at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.onTargetChange(GraphicalEditorPart.java:1017) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.onDescriptorsChanged(LayoutEditorDelegate.java:652) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateInitUiRootNode(LayoutEditorDelegate.java:574) + at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegateXmlModelChanged(LayoutEditorDelegate.java:347) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.xmlModelChanged(CommonXmlEditor.java:327) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor$XmlModelStateListener.modelChanged(AndroidXmlEditor.java:1569) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createTextEditor(AndroidXmlEditor.java:781) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.createAndroidPages(AndroidXmlEditor.java:294) + at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:284) + at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) + at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) + at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) + at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) + at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) + at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) + at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) + at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) + at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) + at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) + at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) + at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) + at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) + at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) + at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) + at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) + at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) + at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) + at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) + at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) + at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) + at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) + at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) + at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) + at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) + at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) + at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) + at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.308 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.311 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.312 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.312 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.495 +!MESSAGE palette: You must supply a layout_height attribute. + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.499 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.500 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.500 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.500 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.508 +!MESSAGE palette: You must supply a layout_height attribute. + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.509 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.510 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.510 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.510 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.515 +!MESSAGE palette: You must supply a layout_height attribute. + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.516 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.516 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.516 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.517 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.652 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.653 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.654 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.654 +!MESSAGE palette: Failed to find style 'tabWidgetStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 2 0 2012-07-01 01:03:56.661 +!MESSAGE palette: You must supply a layout_height attribute. + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.662 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.663 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.663 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-01 01:03:56.664 +!MESSAGE palette: Failed to find style 'textViewStyle' in current theme + +!ENTRY org.eclipse.ui 4 4 2012-07-01 01:06:37.418 +!MESSAGE Invalid preference page path: XML Syntax +!SESSION 2012-07-01 01:59:50.839 ----------------------------------------------- +eclipse.buildId=M20120208-0800 +java.version=1.6.0_24 +java.vendor=Sun Microsystems Inc. +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US +Command-line arguments: -os linux -ws gtk -arch x86_64 + +!ENTRY org.eclipse.osgi 2 1 2012-07-01 02:00:05.627 +!MESSAGE NLS unused message: Preference_Empty_SSH_Path_Msg in: net.rim.ajde.internal.messages.messages + +!ENTRY org.eclipse.ui 4 4 2012-07-01 21:41:31.270 +!MESSAGE Invalid preference page path: XML Syntax +!SESSION 2012-07-03 08:06:04.825 ----------------------------------------------- +eclipse.buildId=M20120208-0800 +java.version=1.6.0_24 +java.vendor=Sun Microsystems Inc. +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US +Command-line arguments: -os linux -ws gtk -arch x86_64 + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-03 08:10:07.220 +!MESSAGE projectOpenedWithWorkspace: failed to find manifest package for project library + +!ENTRY org.eclipse.osgi 2 1 2012-07-03 08:10:09.194 +!MESSAGE NLS unused message: Preference_Empty_SSH_Path_Msg in: net.rim.ajde.internal.messages.messages + +!ENTRY com.android.ide.eclipse.adt 4 0 2012-07-03 08:10:21.189 +!MESSAGE fileChanged: failed to find manifest package for project library + +!ENTRY org.eclipse.ui 4 4 2012-07-03 08:27:23.654 +!MESSAGE Invalid preference page path: XML Syntax + +!ENTRY org.eclipse.ui 4 0 2012-07-03 21:48:58.081 +!MESSAGE Unhandled event loop exception +!STACK 0 +org.eclipse.swt.SWTException: Widget is disposed + at org.eclipse.swt.SWT.error(SWT.java:4282) + at org.eclipse.swt.SWT.error(SWT.java:4197) + at org.eclipse.swt.SWT.error(SWT.java:4168) + at org.eclipse.swt.widgets.Widget.error(Widget.java:466) + at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:403) + at org.eclipse.swt.widgets.Control.redraw(Control.java:3402) + at org.eclipse.swt.widgets.Link.gtk_event_after(Link.java:353) + at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1738) + at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016) + at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408) + at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method) + at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8422) + at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245) + at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) + at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2276) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) + at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) + at org.eclipse.equinox.launcher.Main.run(Main.java:1410) + at org.eclipse.equinox.launcher.Main.main(Main.java:1386) +!SESSION 2012-07-04 09:07:21.321 ----------------------------------------------- +eclipse.buildId=M20120208-0800 +java.version=1.6.0_24 +java.vendor=Sun Microsystems Inc. +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US +Command-line arguments: -os linux -ws gtk -arch x86_64 + +!ENTRY org.eclipse.osgi 2 1 2012-07-04 09:07:47.079 +!MESSAGE NLS unused message: Preference_Empty_SSH_Path_Msg in: net.rim.ajde.internal.messages.messages + +!ENTRY org.eclipse.ui 4 4 2012-07-04 09:17:18.994 +!MESSAGE Invalid preference page path: XML Syntax diff --git a/.metadata/.log-ajde b/.metadata/.log-ajde new file mode 100644 index 000000000..376a93a51 --- /dev/null +++ b/.metadata/.log-ajde @@ -0,0 +1,5 @@ +22:28:47,634 TRACE [AjdePlugin] BlackBerry Android plug-in started! +01:03:24,013 TRACE [AjdePlugin] BlackBerry Android plug-in started! +02:00:05,849 TRACE [AjdePlugin] BlackBerry Android plug-in started! +08:10:09,350 TRACE [AjdePlugin] BlackBerry Android plug-in started! +09:07:47,125 TRACE [AjdePlugin] BlackBerry Android plug-in started! diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabHost.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabHost.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad4e3851629932f6233263a1c311b9dc547a8c3 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*W_W$&~1=mw?n!PZ!6Kid%0F8ZrWThZcPG i&*g|;0Avm!@W6Ec6$VEA%m?#8j`no*b6Mw<&;$Tgkrvqi literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabWidget.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/TabWidget.png new file mode 100644 index 0000000000000000000000000000000000000000..2c157fd0949cd6fe5d6461d66bbdad8c3199870c GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^nLs>^gAGXDbzAlgNQHR1IEGZ*dV7$O7sxxb;Jbe= gKf4H!Nj5mp%=m2`1EcTq`W}!Op00i_>zopr0C$fTM*si- literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/preview.properties b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/preview.properties new file mode 100644 index 000000000..e1146f3f0 --- /dev/null +++ b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-apptheme-37inwvganexusone/preview.properties @@ -0,0 +1,2 @@ +background=#000000 +foreground=#ffffff diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/AnalogClock.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/AnalogClock.png new file mode 100644 index 0000000000000000000000000000000000000000..66679e609f8f11f20963aa35af7d0a864fcaf84d GIT binary patch literal 2193 zcmV;C2yXX@P)#!_^Pt$|`2X2%@5{Suu+V%;1ONLr_`P3+bScyG_1hV$pPJ$<_Sc2}LMiiwGd5yEkVKM5kVJwc z{s)Q{Eh>{IPnN{QM3QJLI(6zKA3uJSD_5>a=FFK%qK)X>xwE`{`BE-lzARa@W+jO> zqHWu@a_Q0~*}s3kWXY0+B-)6Cgany0XO7ICJzEMFE=&?_MBl!B<<+ZKdZadQ-kc;x z3MEUHl%73%O08P8jQ2fs=ur9m`Llfb^hvsR?{2hj9M2s(bdYAvnvukT0|(0c_wQxT zo;{K?XHKJiPntAIzJC2GU%q^i!Gi}I?YnjB*1F5jpFb~U%9KgpB(`kXQl33~raLAn zDamNx_!fTu{$0L(`z8}7PBhkUjvP7U@ZrPq15xy zaYM?MEo-dr#ful~M5Aw9a7>MN`0(MnyPrIHB6aK5<#7sBsZvF5-n^-kJ!8fUohY|` zX3CUFR<2wrXdrUw(xpbm8W$HQ4<0(+_W zR;^m4#JcSlJK8xlDp#&d5<_pPr%#{OU6YcM;(9mc$&*L6Y}pbZaqZf*O01hc8#Zhx zZ{EDoqjb=qL40C_L)Wfd^``pb#S5uXqlT-#3KS?HJ9q93khppCX33p9x2ryJd}0@# zJb6-z6e&Uy!vVLvsZ*!QtXZ>M??g=U!Gi|_B<|R;L-Oa(@2bz5HET+8a2_}Kpo zC|!F-%acT#P^V5EdHeQlfW+s| zpG&1ml}MsZh>wrgH>cCEE2~wjMiOm8t5&V#!-o$660s|>J4s@gw;0S%a3`5CTAM`2 zjvZC$=CpV3-bv%ejeYkF>esKI&Yx!_!Xu9(3*Vb1OP1(m!Y>olr%xaCQ92FdG&EVR z0p%S`jCl57jAzfDb!|;bGl`H??B2aw2LhYo?c29y%$PA!x^!vJCu+!$A!?|08g^y- z_U%0%SAzx(Wc&8*x~O36#|D@(Wr}3Xn9;j$A|w^ivcNS1BH>OtckY~Y>(-J0@XUI2=FFMEB8N>E8Xd!n+?><`H$bc~xRXptBGQ6|3m58QavCOY z)TmLOj0MhP*m3XOyQj|Y2&vJ{>t?D~ukP8672lU-%a%!S!_f*imsg9bRH;&t_M$}B zn+Yr3(bqT)yK?T_xqK(u0!RwitXU(W4eB?NXbGUN*|cfXZzL{XzC4;k+@k9T<;#~( z-(sN+7p`pCvXMj^fC~iV7@=+b`t`;`1xR89!@Q3jJN6rikTB-Wo0lZofD$E2XrN1I z+qG+#N*PI_1&ED}mFw59|3)Gtj8PnH8eKoALWK$%>=N4GHGun!Bw7G?@DV#0+OA%` z8qH#<==wnj$U)3RXnXkZq3%+WXaSluX`-I|(1zU!n=VPTBx^>nNXlv0op8#ML<<1v zL$JOkSZC9sMGKN>1N!&x|BJpRSfYU}QzX#>j2=B&oxq_D#3EZqx+D>1EUaMUf(Zx6 z0}Tj$i~+)VHYF&7-u>{bVLScqL8pL6o zI(16gwQEOthHXGRA|C!A&kw3}l1Pw5l1Pw5f+P|okt7l%ksyf#NhFB`NhC-jK@v%# zYanYqlAcGR{*#SBs*@2TMrcu#2!_^~$(R9&JjjDc7oPMD8#a){e}IHTj~_o)@z%wQ z7q!A_1cYVo6CGfcA=UxH9|)3AcEG1u>;F1Xk7NA!@fxXx#f|J%8#iv0MvWR7DY)W_ zL>v80#BSc5lC!!=+GfO%{(Cy)j^>uL-{$J`y}Z90};!}1c|V8lt40&=Pm7j zjG)bQQ2sok`32n8u;M$B??i$m5+sozi6oIAi9|G$h#(lhT76*TuUD_03F}Jqk_ayd z3Vk3X&5xO%;7)q<=#iGoC5fp3Il5s>MArI(1q=Faq7W($cM|F{!kA4G!}#1#_ygV$ ztav{jr@3(;G0IVk*L$d(u}4+Q*ya3}epY>{tB?9!!+ zrtw0u1eDD4^DPh_dH4j;;7&q%m~>AfiZvq-DR$wC6)TLE-hsvk*@jJ*J3@Xq_)(!? zNJ>f~iKrh4=P161xW1e08wq`IQ9?QqlcjwislX)+mz)b1F8C!Qhj;%u9Lv~=6DCYB z?w16K*x|VCny$};=g@%z2W0i?)qeSgdpiIWBZ+6Xn}Xcf7>TKP)xHOI2bnIlX?n1mQv$6Q5>P;!T6n4GyMQI63P zD|f?YijcJ&`#Orr)$dck@8kF9@BPQ?@jhSo`}KO>x3xBv0Lz1ggoGr_&Cc2h3GILb za~+TvK*LRo41|P0O!KqG4k4rb99{*~5ZYNo%a5mF13{}v4`>20Ffkssm9MV!G#*10 zjN3wGF4QJqY6~te&;;Y#k>8f5RXnUC^V@m}oLg6UT6Rb1}B$^h>iMvoA~@e2nhRK4m$}uF)*E%*t#c%yq@=+B@A#*45Y& zEPP@XTkZ!tiUr!E=xM?`cgO5vrK{N}<5-m>H)_&B!}9sN8>?2%&#!urO7HwwHW{*A zFbG|?rK)3;3&D=>3(j!?eah3TTwe6udg!(SU{dUc>R=NJHi~Rs%t0jN;7`)b@`?`#J|8F@Icm& zZ@f6p>S$1|esE^^#%kG(uj|#AT9k&vQ!K9Ek{niRqmGH)t7iSwnlSxVdgUkJvf-co z6l9h^=a~wcdgDuvZ;)oyY14)Gg>hV3ec{$nnf;8BF#K+<3uv?+w;v;SD^E__Tm8wi zrtPkbqiOoV*H(yB3&62efGr)Y)vxahGvb|H6JYM~q^ySax=8%U@czpWIJiopOhPz{ ze!_YNd3XD1(uq53_!SqjPQZEI_1V8`!H$3fWuA1~Y$;G(E>}9$namDXsCji~X1LM9 z-im{R1mm)*TvTD2kWJUd z8^zDu3r!?QdN)ga$+X)7#As^}Kl}SU#~#qTR7XZ9aNM6M-8EUvKU|G~am&yZndN~L zqwq&UQ-Ul__t@U?mgm0k)m@^NT0!%ex-%vEj;r&WVHa4NCrSD_ws9pGJ23mb9>+E* z_AFia%t+RNEjcVL4vL_~;K9pZdKC!AVyt<<53(FunPb=J@}s#;8T>fOL(aSZf$0a0 ztRLa$S=IXuKQu$-90_2R*)xig6?FS@HD{UwWC3VAOgtUPrJ4EkrJ&UZp8w zAp4J>)CTDz`+$6SC?Ou3FM4#`YoPgYzDIlPg_*}4GvD79`-L@V4KhPB;Z9St&aUoj z+I*s~O`d@-#|N;da@8CRapZPoSn=df`8iy{9&~2&)ewlTFH;$8cq$GF@mbn)472#* zDx)$teEzbZLaK+Xv%k)@kFwvimtA5HiyqCCE6Ss9ZT=V>uD{mtrn+Zlm{Aj+RzQ?N zNPUcSt$JwG{<=Cl<1i5DQ8Y%_+f-=D*f>LxLo5!4NQX^+agKpb2&~9D9V+;t-|y~4 zanDhyE?(>(l|i?OQt&msl-R@_`Wtu$oB{%VCc3zCx8CBOzvaX5>_EA+W0LS6jluho>W!!y+b|8 z*qPH7Ya{ao?|3~VPk)CRH$!+8y24Ql*6aJBApq-TR)Uo|>Uh4lGR3Dq&#=0BxKtPq z^G-5`WV&xCi;7lU|J+$(pLjrzsTKICHQZ{v+O^sFxbB2mF9q558Q$k-+ncM;E^-OD zeniT?w6M^$Bn$3jH%_}<%9MWOi;nP5oZG={3BB2E0CGO-fL!*Flaue9d?9{c3jQX< z$?zwq&WCIeEhcdTT|EG^$qB(DN_|&uhXu?6fik9p6YtSoM*h?!!uXrJ0TXp|B_otT ze~2N8(8;fzaz;6%ItA*JI(dID-GI@P8n3jzgLaAtQ)1|bO~DJ-lsYa*R>-OzGl^Fj z^Z_dtP^0p#ME*=Vgd9JBGj^(K75-BCOOMD!NQZB z&@w2{Y%Lj;+ZrUiPn#I9%-1;AmscPT ztMBE$AsP0(r1mBoC((_(dt|#+&{AGzk0c@5&_|+u1kl&PQk&s!k$zp4EaJddAet}s z93DCQp&+-^ioB0tG=L+o*V?S@K)w!imIm5BfC7NtPdulN0SEvE0A%os{CBBn4B1yu z^#c!5ysrx5{{joZ{%^4G`$kI7QDB)SF3UO%@;LA>toX&|f3RYkhYXK8M*5B|<^Ui^ N$o!o3*=iJ)_#fmIc#Z%7 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Button.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Button.png new file mode 100644 index 0000000000000000000000000000000000000000..6b1b8406bfe85f599d325d1a82a2d36c46410d74 GIT binary patch literal 1232 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 G@V@|QE@ct` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/CheckBox.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/CheckBox.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca12351d4151138bf4f0a6c89af03d8bdbb5f66 GIT binary patch literal 3592 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 cGH-v~!q!NN1T>$We{U zzDwE0GKjG|Pw)AC&N+Xdf1c0vxt`~`ukU@|*Ydrdm`4w_87^PHOhrY-psNFWOht78 z0?6hd8sPcYOIKbhDrO;F7}VH*asxxD8i8>}R^-C**4piizHN#taBE{&`z(}}TUbw>xdS&yWX2I@l#NtuIOjZ#Vw|-F9!Q=zH$v7&8L&T zt3w5GY}8OEHYa9kD6q|BbV*=NTBk;e{En=U+;0Oaa;^d(w93jjehljxdgLIGvS^zMP z!2`ZQ`sk7A47E-k@7m0}j#|jZqqP$EZwku~#2YBHL7iARfAairO-{g4=Gj&Rht+sI zx7@d;gCB95QG6kuEhjs1L8p6TGhB{23+d0ix(SG9ZWZm*Z>8*}Uvu4^mYYK@o*j`S zDW{aV21jf_M?9a}ta#J!p=+JXfGV+Uqh`u|^D8Z%&-0MOf@45611!5z)^Zj&_Ss`j zeZvg3-9Ce+V>^MLp6vGDC~w?}ZPBt&x?4vYlnbKJOVs|Ow18%trk8AdG~(~)AR*=P zmI*k$7QRlkvxC;){Rv0+$!g~il!d|SY?Y(oc?dRWQ-QLWs8+9be)9cu_CBBg{44j_ zfaTK34*~?yL)VcaLq4?y9M+~a5-EIl4z+t2fv|UP+8gbyxlaQ*GgLd3*%b%{w(MTj zcdul;X5;hRY(`)99mqFcziBByRLIe)&|H+#X6@}NZ0OlxCohWpwQgf|uBGL8t)yI< z^tTV3N>k9M>4+xs3KwgT+Q@6a!8+=0b$q}^^H%fmG_cD#R`jQ3Y|v4no>kD{0j_bU z2aNNbVBL}Z9C$P9=L@C%aXY&>;SHh(0gmNp8G{@(v#P)RE@R(FEE~`1s0uUP3};d$Z~U53 zBY(MAadU0=_PcfU$8vO?V6%dAf1NufWT2&8HyFRs1_8z?H;O5N-Fy}adY zZ6AQgXm9#Fc#pAP&y@|qpc@PTTg4kFuH##6T8xdCBE@==hs$OgLmCZ0(IM z7;8|Kl-8Kbs6D!ct6%$Ayq5!nosr7tX)pcnptzTeL>!)QxpYM5;b(q_H*m~BX>bm#^;N_xBp>(wJ-Lg9-6qc&s3%HSs1k9s2Q z<8chtQmK$0yfCuR!?nE0*WI#T?HpyCz7Z-udJ28BSLTyA`mJaEkMz+?anPq+ih&58WjelgYy(7&|o?bp_i=jIPgo7H6;N^ z)}aUUdn?@YGiGKGyOGA0qIV(nN!77ucX49H9HMdf@xZ9acVcC=1mwn~i91787T;)D z!{+3xpGnc8P3zyP?W1^oqeYZ<^DCg?GyxI60kBKgI&)cNW6ar+RuhS8XY%#hL2FWV z#C2{7;k1s1$H8fkEHfR^BjT`)R7R^*J7?QIm*vt9QBsnSWx}IffsH_V)UOsI5%fJ1 z1B5hFhk`UyuYT2Iw<31!_aHH2eh>Ut8d<~5%44l;v3S3NqvX+k=}F7P!^W?E7wu}K4f$8PJHXRb7a|*`YQguW;V{b7{6EVJ*p-Wm5VUrz_@bBk8#sQCjwMK<+V8 zG+552z5B&Ar7%y~={|g@Hgo<1Rfi)0ShU%bK6|NuG~p0`hglh@QbsC3?B#<>Fd$NH z)Q#A+)}YL$;16znM}Hw}#Fvna#=vD=Yiz3#wjy7DVzB{yoR!zWTI!`c33BRRm#^*-8! z)rO_-9H=as$Oz~c2=-3M>+w20#Dac=u7dcLr6$U3T+f0;61#{Y8J7k%Qlw0KcWy4i zx;bQuUG+uVNSg3!7Qep-0%W)hV{TjyHXf4AecgOPxi=+O!GAES*~e_r(g&wblJW-k z1@R=J8c$;q9}roM*li-V%TfF_Dnx&Y)|;3o_h;|`LE47 zior$h%e%$tKFUx3YBwA9vK7Y+pRKe)t;kV>AcC-HxMYrepDl73bDpgXV4PM^ zy%19_Nb`rXipc@;*DnEqa6Dt`T0lbNgR4D1_u_Ta#%Pr@GE;L49E&i%E}S+OQu`o7 zxO=xutTnHwECQIomy$0`|7n~R>K}h-7&|9G8J(#gm4`oxt>z%!Q@A<{f6D7C89cD0%!PWp;;G!=3s` z)d1ao6VOGxzUT1o(O1)9uJ;#~>M+{47bWqK?Ogb6Cek;69zkKfX7T)JA1D{c&F1@I zcQ(rggKtCMHR%%~qq$){728?_ap_qMm)MdL-AR(PlN`EBp4><(YxuTI7X9&Y(1{@Z zk66B?PM(f-`WL23p;j#;%vDxV3%4U;r}Nryamcj35QJuoM*bx9eTYzS*3I6U4;UOI zIP#aLsJg0PeD2mQVt%_|Us*oD2K&wsfdOKFB(KJRW;GRyeb!esF{MU;%nYv zcy;yB0w4hv_TuM*`v0Kp3?G_5pUM^#ci5LZM2>Sjxe>AKT!dlIOw$C|A=IfhElFN6 z=k~4KDUX&JaiFP4C0B;(!V~u{ut~-$=ZHB{IBo$xS<^Oa`dZmICC$24fIc4Y<(JLH z7s|PV@aB6bpfo})oibzzxGkuYeM_ymgX(S7F@O6@Avm0*wAEN8B+_+xNO~@Q0)qpn z@c@6P(QR?|ncIoVKbWG?)dMfzkm(&&Yr>bNl80Xc^g4BI)tw)fBsQwXFKRn~z@gco z0E)!{3_NCl=ex5Flz;U)wzT#Rob2?;YWolOzW&ghy5-+5R#EWFEiBZz2#}aF^eSND zOvvJWHATa0L>~q!ahUH?e9^_srv14e;pym>f2aBnSbwb+o6Og`99 z{!6dHajfgX*G!-9MTV4m>Bl1ym0e&HwscE7nH|b+uy2$Q5iX?FgAN^i^-+nt9-$SLltH2)H-l@KH4)B|x!Zs6n zn+RHuJjq2)k+Q8yq6EVPt5*)&n1Y$$2`?+hSZgZ?$C$@VP}F+O$ujdE<%Hr?Mb);r zN6CSJ%i(u4eRxsIHTPA@Q=RaXD|{c*@yU9@U9U(v1!Eur*gb`$OBYQRPB{=A>38n* zO+1gHBn{MltFSj$2CV6BTHaM?kaxMP!a&b@jw2uBxzLH3-M}!9DS(Sv(Dp}lkefzX zZK)<|QzN*e?uLG(k6o4$VAy^CLLW2-(j#TpF^s_{)h4$Y84~iW$`W}Lq=!5NjAHOR zYg?0_N?KICmmc(SK+z^NI>gu4?ufZk*W>c9zJMi7|3IeWJ*5 zsNtz2pJaO72I{ub+WVdNl=ZR2Ac`4;`nei5| zfC+4720cDLmP{risZ>gm$t2?~U;z`@%nX`HB#1c$6*e=2#$qu7P6^l$l%ND9C_xEI zP=XTl=Y!&6`0(&>sbS@Zl%;}3A`$WVe6qg2zSKY;(3f8gdT?-{4kVw?%gxP=)a&)7 z1ahMf=nMMvt3kb9uheQad3kw}=jUe`4u{_w$cfzO1NveM&`PDE4yxDd$-~2gv|255 zyNH;~ft<*VKG+Tv2k3IS)O;cyce~vS3ABwI$c3D?1jWk_qXq{W3WZerJ3BiI3ABwI z$c3E9ZA(y$7K|Vq^rEj7kpsDqQyb9z{e8%x;xR8FoZ%zhd3)rixEA`xXJU(@_qWx(=T7b6OZH0uT z2$Tfg-Q6j?Nla{wS@!GeYc;32ySrjR zsgZ5$5A>&}Cn*+-3NR1|sJzi=RNc4r1oNz*lc?DD{{G%PMSL9HcpUI2CnxGOpv8>+ zJfM@P|GIBHhIX-Zj5jlYA}2wop#ELc`&Z`u)Buf^Wni$Mh0F zAP``-*Xz;we5T{^NT<_DtKbv95rZ7lTL7I-hjp^s?PxZe(R@A^)(Ocz;1j+P!^Z&V zkhg`yVaLX^+&6qG0YEzOuROLnA-Qk(gl{DPat3q>J`I2YFaQR?02lx*09d!HenV>k zzjNBLaR_YI2CtXvFSE(3t4KU{DOZ!C=6Y%jLw7e9V?30NHHT zHtBV)5?j z<~o23VK?ODYsd`dPCA`tzTne!fS=~dvwLp0n|PnVr?R5{6M%O>FPDox0M)_}0zkD| z^=<~P*DKZQb>{#wnGE~9TCHfgTq@Uky{2-x>>Pm3ojGNXQO|EJ%A32$gbpd&-1Y4C py5|o#%pspS*`@000FiNklFKH9e)wQKJw0J+YDy+d3q}8l5igSD0WY~;US7^SRo}6L_wNPjK{wo)zxw$zU9Ubv(ZES2nb8|B(rm?JH zL|HJIgn{Db=B6~5=rh+}F~RSxbeQ$^^{fp%*6Hc#f8!NI{&bu=_INTI7Nm^h4JbTJv(*w_f_mX(!>!u0U)VAr0W zo=7qk+uP94P<1e|`Dbhl4Gn>&rY3J4i*xLmC9|Pq;*iG|Y*+X9_j!f8WaowLWM*dO zm-0-SJ@lJd#~$6z&hCp2c5GQ$S!C{DVPPQ-v#F`++nJ2pzC}bt@a(Lut&!1LU0oe1 zu9<8(FfhQo5+pBsc^_0!2?rLP7#LnnL?xL7teHC=(_MM&rW5 zg3RweKR?gy-<1!OnP=j0#=aFJ5W5si6afJNQrkeRL6vdk;2npjV10cZ9v&V@gf1;D zkrRZ|Dp?6g@@l~Q7^4#X#|MSuK#cOv&Q3Cml_>ju*Q*8WkhsZ;{-Q$xiHV6}VPf=B zm}=kBDQhV5t6^dphLG?LA|?&&X0S+aYion8 ztt}qN+S*$BD>xz1*4E~Y;)DciQJkh@7e--<2)-9jPEICoKv!2+30!=?ge@+1MObtT iz0;vE>5pCiUHK0-dGa4d00AHX0000wUTFuC>>>XP>+G|M%bLp`DF|0G})$2M341 zHMqG02gea8@a_gW20S@Kg5)_kz$w?vO&r7Nth_B-iRQ)?C>Dvgg6*TSsZE#;(q-91b!xXAMC7K zIMn_62lU|MPus8)$A96);$(098raEXGS^%uh>^JIp6A`=3*;9X#Rt0^R`l7Cw-8_# zK5Wnnb$ioSx}l|=xi<)C*ZA*u7imRY;=RjVqQ9D3>H&1l*!dG(VL)|lV@6M)E z(jGnx={?Lo??2VBF!FYi=PHO>Gn!lT!Ue~f*!^vLO}m2oW&};gGH*QN%{8$YZ{Tc$ z&iIy=mU`RQMq_NVG33Vt-nASaA%%dkI{zR4SOzuU%--hp$j!xUY*toT*z$y-Q-raxaeTDF z^GwecRdAU7%;CY_rDa8FY4ux7L)?ZSsL)%3JwI%9>4LjQTa4%J#w9*PU#@P$kN(%> zme%M!`dd;x>dVbBAl(n1qsUK>P~B;Y@Aq1G1m)n2CS&E8k66Tg%_Hm#M`TIcaHWObnRXo^vq> zyd^e=Fl+quSc-gSZ6x0&y#^k>e#WOx^{&YMQfgfT}X?% zui3Juw)UWwqGXw8Grvh6J== z^DbJTWe9O~zB50pX*R(mCHr}$DHwty0M$HGkq{MCA^UtZ)w&$M^8G?G z7HC=M;?(C1v&da`IkYb30D~Ld{&31=-XZU`aqPTRBznW83j3#yyEC}o{BWSq>=xa` z*0P~wcX4PVeFarM>e(9QYTFjQM_AG{%Ugl8o@cpnltA~>PabpAKb8*MSHfhVQer<^KWMpoyCE43M;qt2zI z)zo@1HJjNsHgO@u!#lA^2;p&)FQNcLfmv!-tR0rN=VVD9*xf`A+5X(W`0zV zssh@Yyw;s6e_p3__y>w!Up^itVW{ALZXC0}T_c{W0(&%z5_Y$5y){n2(6?77{oH^? z^MfZECL8=!MAlSap8Eo$`Tf#YgnzGNY${P+(nACqRxZeOMW+^WF>s3QAm`5&#G*GO z;rS!8k}GCey!u(XjwErTsBNX>q0CcGmJKfMd8m3iH4Xp||L;m(!cTQWXQZP%0@x{o zn=iZ{0DJcYb*0Kz;@-N{n3gK?%&`e(F%6)4`c!&lJS7g>7 zRjXCww(_iq_bF`Z6I7WjZ#wNxu%7WfLeT$dEPRUAkwXSxMs7ziztr-j!>Y1D(u~$< zeF%UL-5`sncP{r2mbaszy*`9LGGM)_OJUqtsH@7m=J3^`{m7v*dxgqM*^>{HJ*Imz zS@gR1N)huz<%1&)L8I(gshu%q7)bRyW(u}9BpFQE)>Dr_rA%T6d(HZ6_IfOGP%++{8;LY1FW2%latfI za5+Up6-q{4FZ}?W(13t?p2a1?KBe{rGz3sTmS24m7GH6j$2(Hys~9n#(R>erE%v@% zNGzNLsB+Vla>yF1v$$8G@8BPnQK$O2$Wx@sp~O;VWX~rOVxWp_#h$rQ%@a|vuz&Vd zKv1MCC8uJmUZO6EVLyB)+yX6koXm$kpM~p{M|Fa{zP822<`6`rGDj$qas%^Af#))*n8YRv;hLY9nCR3phq1I%3`#)G63tj{ z&q>Rz9v<|yF{D%&`bYt&a`d+{0m!9U&45LMpmCWO zu_^y`dioV0^_zkn6)rVJenwn{fO{pWPO^B@o$}%9>+4_o=k+n{vL#K@X79wr#A$vk z{JgJ%_DAF7c#X52*DWmv0ZhNFXl)e4t#5B{2LQ%G6?&r+v)?EQfoLuW+IMH)*Ey-c zL;O=GTn^DIl$H(_g~~N2c0G#z6dfJSSUNW*CaJTg>;m{96^TT$FMxGJtcjXiogb2D zd!AFw_d8W)DMD+(ZL5>r3%KF$$5Eh*n|GaAX7G@}wD7BPH_o7wlal6D2&gY78G^k^ z@?zo_1BbqMTfnb^Bn2@kPo4}x6lJv!yXMXjFdj=FET&3t-;YYAVlZ$xya~)3!X+~p z5|xFK$9TYm4UNWtu5ws+YQ9Dbyi)sOw%}p@Fd`Ec!MEl8yR| z%=Myt_qRbih+B**$yyoRx%b40;_0gCFCU zEE=cI0)x^mL6MBusm~(W$G!;-22Zt&N&RYzr_?fulB=)8h5SlKk}H3j>Amh5PLfj|Zhn#;lq_-%X7%#)@Te%Vr?1+xna$qb4kzI& z07u)!3r~x{b$|P+!x&9evI5J$<>Eh&QW4}2u};}D#UPPIh{j-__gq$;R<|ZvT%}wZ zy5D;$wW3fEWZy?+Q2y`)n@%C>IdkzFmN-=+P#PKNEzb7SgsIqgA#6BAoG-nT#zXuDYF|QnWvIWWgh>4 z_4Qk|S7+SkINy0+$J@SmI%hw_+Ru4@Ydyn4OG`_O2&54t1VI2oAOQ#g2sKi3b2It+ z`l2K$h@zn7Jj@fyd)#ZkS_&rdQvJ*_Y(F)=Y@a&nSfUtg2w=Vx+wct~1XTZyx? zvs@c9Gc$VXj*gC~&H4E`_0itmUgct~Od*%2!|_v7Q;D&$F{!SuCVP8()6>(*>gprVC`5yzKrly9*N0x7!o13)RX>4qi>$|I~t70JB z-QC%9P*9LeM=dQa$=ll-+Z}vBz-dm_*49QmJw1tog9AxQN+QR{$1Ej^?j+F6%nY+@ zX=x!|US9O{q@|@XyPpCASzu*lg+xU~5ho`n5*-~)c6WD~9GjE-y}rJ_w5h4Bt)+J0 zPfScG1_IB^%ggk+qoYHnqXh*8Vy&(`Al%&C*vpYpB-iow_Ga?p;$p@R4i0AP$@0P4 z+L~NkT>KaiNUKIhMq)BMJ3I3F`pR?$1_q?o?dj=ZH5i*&ArM(vS@ik-{$A>ZARIr) zkrVj}XMKG=<-NbZ6AKFqnLm1AVS(x()o?t~V+}CXInb#C2zj=1b8}3`-``(Ko|u@( zF&s5cA8Cd!C|g@wl((_5L9DE-WD*J(bkHPlc57>El()UT zt@g?KPXf`^)x~u5^z@|Uetv#TjzX>w2oO>UctBZnF>beFqE-|XoG5ukT9R;TI6D+H z@W#i-e-#jlT54=uPM(vKqZ|-{fq|?rIXXI0p1!_53sPQQoCwyimK|-d+I+P+?&q<)fe1 z*4CzN7oJi5m2m(UZ{RI1E`AFL3~sX0qB?-!HV5Bn(>Nf|>2NI>iVNBGOmB<2H5<=j10Y-}vEF*GzJ2L}g~j|slAvXV~xm|{~>QvTOu9T^$P8( zSy5-s&d#U}ia3IZ9gO;=DiGLQXut7(bb#;$Co?=eTx{C^>p%!3{1=Bn0uTZa0tr9} fKnNrNq51S5RZoRt2H@XB00000NkvXXu0mjf5oKGJ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultiAutoCompleteTextView.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultiAutoCompleteTextView.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d1bb2d05fcfd2a454f06a8c574ce22e64f5ac4 GIT binary patch literal 2687 zcmYjTc|4SB8y=MGG?v0xMz$C&bQpY%WS%HISy?^(0-Ov3#SE3clgr7%(2LuA~o0%HgfIw_8 z0Bdq_0xQm>isKdtuvfhp#HkwYLP55vp;3%I~y|3tXJ=;4*EW#>eNE2K_4&W=?h zc__^$fwwEdAc2qDOJ0OwK4tq{nBv#4N*jeR;|mq7!1;8nJqLe|y!S zHEIJ1(G4?CmefMcz0JuW7)7a{plF^gi&dC?lOhQY z3l*vN=u>HnJ*ZiBdg{@4PjVm$ zuQ+VJH_LKZGna#B^k?g><;fQuAvqeJsLqtHO#&Xub`@#YtY@S#_I=ss4eZEh3lSK` z%C6GJC|O*?xHa;JG3nsfPp1a&p#(x^r$3UW?gBigj`ihV)O9#6wyw!qo9huyS9hm3 zD^X6Fq?+zbwc&*MB`%z+wr%jTw(xnU3#cLw1Eb$7QnJoEvmB_G;@F`-p;a+KvXpDj zf)bry#+W(yj!*`J7DuWjM+uBttbtnWr_Mxb=-$R+`6AVKG?idPLyi#|eHbdMyBoec z2h6&g{^Kr}iYE*7VmsqFj=}in+^jGR?$8OI89q87d~cMjTH5GS&w;t+c-|9H((4|f zAHNj7dl4Oedu3YR`xJ$=G|{3&I&)nm>BQN9$YoJgv}xo@pZh@m1UhSf=f~onW&VFY zG$E98E=H{j<*2)ZZOc)jO}D1RfO172NM8i=iot|F)VmLDL~njO-JgF^6%qRj)>M_J zb&G_6>weG;w&qSYl%H*%hnAK_|vb6>O1kgk=YXd7> zLjwhR8x(PW8a+el0pa#ySq)pjvS9fIbW(+u*E`wBYO@T*=hYMK+*kFqbWRqWMR(Yf z(V~FvVvlt~!Qso3jQ(|Gri#LIExA}_=ca(ix5gn&IIHg~$pe3BpK@&Qg5o^XoTwsA z0Tb`%vtcXYJ8Sbc2)xcvx#cMJ!&A=()!%$aYZ6nXbd!LA>Mo=KvkQKdFgh{qi$>~f6`KpqNNy##xdOc*vE`4Qan{mu9T;1bsc7@tK z6yrmKw{6iTP!40W!_8Z94`@@_*)6L7IP7OSdZ5faM?F_wzrRCW^=b{J*Ca(^eyr@q zd`2yvZ?x%_^UfYXDUtK!pYyu(nP@Ke!U$Ok?};r^HN7)w;pBp~yvMrX{nq0^ zguVz2vjFqGc-$ortNqsJk>51U`G}<|HP}s!5qp%iTeI$YD;p)s>TK5{!=U!2*!Xpd z`gdwqx*}};F8-L?9sW`sqIbnTRMVKc*f`= z-vN^nXM7k{rOs~f^S9NmKMxsuq7gXV?xv4XNlI{N4*NcqSV;Q(PV$*2(Bp0YM>j{1 zh@xzyaiBzkT;9gwDDfhqb+f~g#^ZUk5*^4TvU5CMAhSjYDf0w4?P3WA!>_Xg?{RU) z#O|yax%E6$SmN&8mV>huIhx_(<12E-p#?gjbZbWrv1WA4KHb-N;Cg>xWw7Sx0AHhT>tPQelmt{@-_&U}|t{JEL zJ58+v{J`h!wK<~#BirumxFI0)^he$!v4l4aUYnOOxFH==M?W1W_hMI1Pex;*gE5zuFH*GA$}TrT1*`GQT-wwQI+ms zg7IbEU+nSMU)t4I>F_<^78u~w_JB|P-9M0vOX^Crc+stdjfdOD!(2t(xe>0@Ztdbf z{F2+ngx}alM>P@R1(z!AbCNPBiv&d9LG0!B>~3US=I} z`zVp!o1b^(p zY1^`F)MS7k%jnlZF5tDM8srWw6-{m%#Dxd$b-6=d^?T*M511{$DF8OhkigCB&~*oX zMBh*n+Ds%E2^|669_~K`z-qYvdmF61ffFyAO$5S+IsS2U|APJdu^{#X-i-=#@#BE8 O1eqD33~MgC;QtFc0~1>S literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultilineText.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/MultilineText.png new file mode 100644 index 0000000000000000000000000000000000000000..21d1c063de112c6a18761460a7495d0a8b84051c GIT binary patch literal 8432 zcmZ8nc|25W+*f2TqAb~ENygHU-N;TtDU7UB23;iCmmwKz)`qd0Y!MS<-?yn`i;z7e zWHu z|C~7;Q1gRS8UG9@E~5WF0}Q^NIoWF_$@`OtQ%OqK&z9YkFCx^j!QP<+3@@S&4UmJH z8}(DiJ=38aPvew;8L0IbVG%eD=#qdcGOv^u&jidtT@<3Q$T79AwcUO-R>P%XLu)%W z@aU@V#wXSso}(XBefBEE(F+8{$8Avy_c4bLDqtT%7bF4?^tK6sB*mqn_vZDR%tCj< zJy%AiJ4ck)>XwTaq%a3}KI}>~A8i(B$8z`e=jr9lXZnfz5*qiiuWH9=6q%O99PX}i zBw-*3--t!C<6r%g`IErGorj%Cg<~#tRkP*uU5(Q zCbZSgXL1~`*sHjCoa~eYY6c!JTW5S1Hq5jr2vmnduCc#_APzOECw+@hbeleNiKf{+ z#|zqh?DpyL5xB?&+pA`SSCf)|#Ug@XKZ7c`;=c{9th zP9u_g=cZqg@N^P2BzD{R3@@woCY#<&<-Uc!oQYfdy^?GoleI9FqpURevsjV)Z);k= zkV=|QeCvHp=8yNLVl#c0-Z^})aqY`jIbK|Fv?e~>2L8?0)Z{o^T;rS>xc;NHZ?9=j z*)*0^?J{Mh0PEW=?}cz!`Yz`6rPyb(BNp|nBiDe??jPpFLdM>5mnQ_CY+=^Mq3>&H( zZ!ctcO}Y*TZoIOlAao@h?$5;TP0qMsh!)uGYr2Prtj+tM_77j4qkFj;cr?S~vggz> z+S#}_IbOVqIoZx%8w&)oyTH0RAdhJXI3Zk823c<*cTJ&_XplS!?90~NAhj!-h2>pY zbv@7Y?j>$1fsf$qJPD-IYB9!tv!k!5q-jYITjmZH3sZ2nL>k|KO#~2EH-=?x^P!c0 z8Gnb&4y+(nxk(4Tf!T)sKba@N%|~+*mh5PnFBK%3&R7gjj!w1jDc1jg)*OIXBn%cJ;q@U-sIX4lsAS;Dk<2);Jrb^KFAN$#|7i-l z#BO4efmI*YgkEN5@f2L*Qu3CBQmSJsRqT7x-x6M7XyLnS6XS5|E}4r~0S9w;_Bd|- zmEbm;+k-NMunQb(Nuf>nL7W;Qv8v5x_`*Ni0j);MA9t#Nx5j-c2LY3-hU zXF*Fkw1oBKTBh~!lIhGc!L`a|k;-@Yb&{bd%NB|Kx()?#N?HZP$}m z?-Z<^nqIQ`P@TW>V9Y2XIB%cZ6+}LF%awss?#GJ4Vv4mr4t7INLkl$HjmgoDRd@tz zyZo15ck+$CxB6-6^vMXx0(sh(vCQL3S-v$I7Koie1FO^Wld+PV@|@+ylLeQ{__G>t z8==RWt!%OW$%D_9vieSUxeh2Sf)x~(Tyz02KZWamj;CPz8+B>^_xKyYPk&OVA_b}c z8RT(E{EhM9xa(wmx-I8rzyD~21RQyLiMclxsczoIc-+fa;A9xPw-8@U*`baY()3Wv z5SwGwfbxSpLTCBHaSt)LaC%*T0sycz3o*7+h}n4U><*N$th2j|%%dk)(>=$Y^nH!4M??!{z;EK3?egwu}#@o-q|&nv#*+U3(cSY)b=AnrzYq0|sS{ud*% zbtb*05PdJskY9leBWakkxfDHXHkFufj6@u)cHu4FDyi{~UAw0p0l7W3ai^JdOt6H` zF&iqC!YqI04h$oms=W9_^>vy$yt2jjgvf8+SQ1MWDdY3>PdP+u@A}N4@_P&WBfy)t zdy;Q_(EMux2MhLtWDj}*Z=D+x3pq<34NWYr0y*+N4X2Z7LjywCJhQ2wS7u$r^If-| z_z=cWzionU5;>pX`=cdjbxi9*hb=|Z$mSwF#F&}I^*fK>N~sOec5LIKB<=V$6G(6j z?prh^b?KlOO}K=W5)!y}E*@cZAU$AjysW{Ftb96ACnHZW0$NUx0x5KYS0P*7QsNwR zqq^Zc`gQz%s!eaqLTpDp+Mhj!tC@MJ{a^>3xmMcHeDK9Z%Ra*c-IckSLGb^4k#?B3 z0w6LSM2p$D8LqZyj`^{fiPujiy;jFA=kxH$I6E(s`$B@B_}ke< z5Lh5UCtyPNR_fF7{>ZHE71hr(ph9sVO}Vq~S|cSs$VE=0@@B_)ZJYQFzFXSjoy(r?4YtFpC+^Xrkb3kzWaWZ&3>l zcz24d^$-AAhu^(ol_*ZcCEtXp(~REZ<#$Yrs{f+Ix`@L@NrZ7q(bq!&2D(ogcWGAc zQPv(}u^vYwenkjp7KGrOMDSAa-BO4QiN*;OyXK)K+Z{f?i9+L|pLO)zcDCK+Q1(q) zmci%M71M`T9y@dl4P|Q6Hl%&R`Lq_q(oW_-y}Y zL-?_jEjn_6C;ruw1_9^HxWDN_=~%_1mR}zvrCd-{?0DxnfrMKx?<@~jN1<#ir9hsB z|4vbq2?KVN9~;GX3dB|Pqhy5wAoPnWu^3oIw?U^Kbia6gYO>MKJQTN*vb#Dy{6N`B z{F@^1M&RfwoHtw!e)4Tm5_>cUZ%5cP4EF*r}cj@N>d%TB~J zW>^LiUQCrGaa9rQ!8|lp>G;@8lIU;_UuKVYs|EDMtm2b!Nm}5yaNjA*PlSW;! zbfsx*3tTT2jNAP03M(^>Zu15N56(CB^stSPn}Mmh!I&Tklvr1)AQph2o8ru4o9Cwi z8Rxdcjo7~DLIo=Ts?zIvJI?d8%JseDbp=XlH9ua`HLQ_SMvZnnmfltAd9$k$+%u1E zxyVsG^VMt!EcoA@`kCps<~n?1eQ#y7e8L00Y#EA^bFr8BRKe2w7;PixC{#^K0>HPT zzb8{!QT)TuT6_G}oKyNc;8rT-;Bl$~yzWq1^D0e_-j>PNdbT&=HLM2J%{O|Hv>AT! zYC1}=Hx#s*9N9~AJeR_^ zo#R|x)T3ZI=R^O&O(v6zh%QlL!)C`AP#h_=zhUW-F?5vR9L^aeio7aejY$S8piX>| zlhs^XV7%K;#}W;PefiTi)@&*`ux#?^wsxN+}>|w@Obl@z5_+6E7pMa zs0Bc(b$=<c`U099?8(ds5)w~*=PE^CE{Jtkuvh}gtVd19_GzY3clL~ z97^e3`10iPyB2|mi}@4B@_Qz%Fu_>LQjn&V5=U1)In@QZ@jE$NLD94E+mm}=Bo&^M zw@UW3Q=4gLoZ7j@E3m^^1uQb$phgb1N+JM0T z_yBrb0Ev(`co>Q^P+YB8_?713S^A!4{M7SiQooA1;2Isr!_B?AG==S5L6)td7eLlkufqbHzQ0Er>&!3*l#GJ5X*6 z3jDTABB=0`iqCFLo=JCGgfqP#J$)>#d(k0HgC-YUt%FkZTzSTqt=`+E93Q_!L+C{4 zfK;tn*f{~4;n|+Bf{1f7AV$Sy{I5B>ap(Azcj#>K#&XXl{tm$Ai+w#bbbyMImh!8+ zG9?)oV`P2iotPBu`1zg;j>e5Pj>%n`8ON;G=YGC5&(?xsu+pbIfUZxE;toaUP3mZN!!mK#7Sy{IU9L~2zamA89b_Fg zuYu*a!WlHz1Abbe%sv@$hZwyG84HmPH|@Fk$OrX4#7kI6<_Q+dU7li>=>eD%H-bRs zRoxxYoB?`C;?V=G%=6c|@|C)X%u{LU?!b=Z`2~!HJi|8EWX5Qp3V#`ADbyQ72l7pg zw?33q1iKv_7sGmir^#UW?eD`M1q^%rw;0jzU7^h8L|wZh@oa+THg5@iWEAs76Iv(s zG#oE-+vDu=xCdH!S4AXL?MW4xt{`gk)+Qqhd3W{pRlS(Rj#MGXQw?6(8cbDPJCvi% z;3ZKUKY4w*`~nX|sVNjJYqahjnU5t9%#B`0wfx5W6e4nzwH#|lMYUKMwctM*rYq|* z%nE|uP31AUte5w9EI*&d(oTQmrkZD=tq?2t%s2@x&-OJ1t`Osy+s;^&2tb?u+d5Ix z;;53HrNJW0wEOu69u(!?8$Y{yA9s;&PTW{E9G+Qr^hj|{+&TH)mBcBnhglDC@q8Bd zu6+&1M_GNg@2O52kEE*OkgA&+AAhL`Rh}BTWqQR^)aJ{WPT=@B2GYpB-R}3YSpgdQgGnJ8#FHB6A=0 ziDd2gb0OjEb~^Z!O7Ttw$04lTc|Rsbn`^8#+Vy7s?*N4sxvQ(a*BNOd^mn!z@8~88 zVngUy+wi^zb4eMnjERET2gCW$ssTK9C72g9F7`2BFgAx@tN&nYzIxQ?m!lqdphw}u z^)X?-5x-*V=BA-N>|^@-on#%C2qJeXWq!2Dae@3(?` zeSU;S)(Y*AvDqKuB*J)gi6C{?q3zzi{!2 zmmwLexF%;Gw=FXCTZ5aKyj{)=I9%-EwL;?LHh(P7UKTa^c$yTe+<^J8>wH_${H&dB z6T5kij6}_kvn75(XVjl=ChHF(Z~E=7gd*_tsVVN|!NGI!gVO~j1r}zRYm_l%(3Ch) z)$;Z~X=h~P?2NBFIb6;OBBxRaya?cUCjxK)8)95O^91^D1D@bVDSAp!+wF!>_H?*+ z9eK}J{dBoLpE?G1@W+gJJ*F$Y@p%(n63t3YZ57-M_LPzkOS=}Tt|SSUB{SKl-`NQC z6Yc~0eWUi6)!8tR^KR!sHz06~4WRA#m=^-Xj}3+LvPr{53bi+asSW|k@ZDy{GX6am zU*`-jhi|XInHjL;^V#<97(CylzF;NrH3b6=sK}dc-B3e}8$PUEhmK*(b|OnXtm@#A za4Vl>5B@SAXy`br9I1rrm1@3M&#CpaqWr_Le}H`Sm@TElt~8Gv#cKI^6IJN12Wdy` z0zn`%ra5*_`UWZ5^a4s+7no^ zq0i;R7g*D_IIJVxEe+Djo9t=zEu*6R-?8QD5=|%1bg@Q>!5lI6xd=N8AAZp&b}6B; ziYF)zYX6P90@)y(Vk(4?RH<*F{;NA>Cj8Yd&P`IW5%91Zx?--=(D8EEYFI-tl8Qq7 z+V|=iwJRl=c~!>jTDat%wTvSD=Z_+rgaPq|mhx>!htt{#>15*9zl2}m`-4V@ai8xp zUHO1k*7&ioLU>&v8sfk3+jD3BfG**5URoijNndo^eJ~XX7zG)OBVKBHsS^Ivbgu1b z48cy$RXR$tJB`$O$U&Ocerk0UJ_9HiMlL}4t-5JP%$}rPET>(@@qKhEF}R)c`mea! zLo1{pehJxv$m$bksVV}&UYrBC1ip~dsc}aA^98n^_!XVf!4tsv8(KX&#NVX*|2D)Q zKVqGDo3z(am>ikH+ye=&Bl#POO$Znkb8>~G9u91T(d6F3||lA2C?6iC5v zT<#0t%z`^|FyD}ebsLlXL!(=OpFbWFk&vu;Cc;o(S_i*wgz;XsCD+Y&aAEnkae$XI zulJhpFqPDENsL$ORo=5;CC7{`r1xD#N)x^>NS0P=cN4gkeKi2w^C&F{Prjv?n+lW= z7mI+y?Zv*6W8%bt%47=k7gq)e;HudOZr@=LjmfKBm&=LLe{37=s-#B1%ljrbXSnEApwuzV-hyt?=cVpOT0zKh(*UvQup<2C8y`Zh79 z%vYfKqkl%&d5&LAOx+3~b87MonKU1vOZ{VlN!;ZeV;KN=AKm$QU=X-b$O~#}N4F+H zS8X5iT{!u~YRw6#`TMS1{k|b%ex&0)%Td>vw%WRi_&bTGbYR~ye)>miuw@y=(gq38 zTY8CzcnCu)I0VJhvLqxGo;2EQ+%7dL<65O7qPSenfo24p4iufmcq^ zXvINhSdivbg>I9y73FI!A*m#Rk}Qf2cC9+`))`PR-IxLN$gJ0NKB&@z~E9;8D|26Z~#($gnzgMG#84osV z&Zgu!+dVX~`;vMyFFIKK$BKp3V>JGi$g^@ zL*dcn7fqO3$Rcn66Bw#E+jP7;zNQitomB^tcpcgg>fK(eCwMxv++0sAPQ^(wx}3TL zs>u!RBUrV1Gc&?y-;cJc$HN^drlBjZwtd)<#>OO;czcs$UUdfe$R|-p&Tw2R8STX~ zLHAq=bkMmEb_L?>7Fcn;c(7;Ml~sswr5^PY;7N<3VZ$$&!Zv><%D23>{>5J=(LWDZ zFviE`8kuH0AMBpha3;;^~x^M9$*VSPvR8}AqTe3LMDaiMl}=x_ULB zP1XpPlqM#$c&3eT(fDjmKJOB9odB$S;Q^`lfR%p|xdFefmxT#D@$qs7biibt9LM1j zu;h4r-)lj=hMf_JVW3A5w~eN)b#8ALFShWo`Y-&_RCBYRT_^8{zgO!{mzQE0!H3W_ zLIl{@5Vv12rys{M9X7n1^54?;;u3Dg_9lG4SG(1t7(AD{<6gb!@9+j}yf--C_2fie zIQ^Mgy)SWh)p2j|z3+?5@jy!So{b?wEivP2K(tw4(+qP1vA_969PFQXJ&-cAppTH9 z^v;puol)+tEr@BzM12-rzyeUKz%ZqY68c2>S5yN8ldL64rSf8a`xLrw;lo1QY#CIJ zaP^)Yf=RY({zj?e9y-6WUx`2Ojb!HC<#bZ4YS0^+4={;^(_0OG`ye4)8{Oo8u=$V* zYBkEbx)mb{ke3?qH5x$8In6kj8I#bOP%_hy2xegg!#zIr&>A;nG^f(5C?JJVw`yD( zchFv8p%Nb&e70WR{tECohc2{OD;Kv??7bExjj;tMG<%&qB!1XXn8wqW&B4xEci6C} z$-jkrcB{AW`QNc1Py^RJoe^PJ-!{ms#1;m2@q!M)?&!F^AL_=xsJp zhRu%syT4%akgUyk8eC~tBLAVqLX5#RMHk(pNEatJx$ZQcUrn* zTDom#+M?H#c%SpX401^^_9UUK{|=|(j|dbPx9V?LpYT;x=o16T`) z_TNXKOaFI!9q{>2#Wf>E79(uhSah2DBV#%1CkW o=c9nr1%504(*ZS!heWmXtzv;}Pc9eul7UQD(?FwG&F1C*0A!QE$^ZZW literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Number.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Number.png new file mode 100644 index 0000000000000000000000000000000000000000..68f83f96a2c27ce988a704b1351f9cd92fc5c029 GIT binary patch literal 838 zcmV-M1G)T(P)Vz4vGugzo?0~0Y*m@JsAvdJWaGD$>91{R4ye*cO;;C(yi z+dW-heC`j&y>2~*$MSifbB52Wo_#*=&pDs0tgNg6@Q?5&0D=V|Sb$&w2o``~0fGe} zSO9_r2o``~0SFc#SO9_r@cDvOR#q0y&(Fit(^D+du|-8iVRUpfY;A3Y%gf7feSIBv zc6P$}_;@HTE;cj}tdBJ}HcXV_VYHMo^4g~9CG&ME72+wQB zm6Vhuu{t|D3%$L)p`xN9)YR03p`oF0dwUzN?d|P_+}vEl1HnpHetv$~-QA5tb9Z-_ zF<2856UlmWbMuS!fq{W!y`!VU@IbKAH9R~V2j=49BFxXvXAD;K$thaf+}wP1y}Z0U zIX~LtGCUBh)O`8!C0t!y#ewPX?+;T`Q*Q<o&HumcE3JMC6^P>%T z!vn!e&BDS$9G8uajgXU*lQCF7qrSdAIlsHR+wefJ($U)58i(ca@iG48FM930!J3?$ zO!mS`OG^z81nd2xuWtMM`*B=mW@eJt-xI8=s;Y2vbMxYwfMC7L$jC?>mgp9R!otFL z2P-cxFRZPt#pfL#A3wV$AXvYxva&L{U#hFC>)G1x2J8FtT3T8R4FoG4OG`^}SXNe6 z;$QyW8?2t5p5&Zp56i$nuu{?4*_mvLS65eO{G{|V*K2HS4EOi<@$svxtMN^!1_pwa zio?UhH=hA~OQx@ur>Cd!F$V_+@dMF@1%j2@#eOwbZv`vbRR4C@d-QJ&b#-+H1*99S z=;7r|W@l%UP{aNO;1lJ#|#b*8W8X~gVop9 zm#i-?F8=Tno8f_A{k32{JUpbbVGjt_hX*UIUl;+w0uU?!!2$#eK(GJ=3lJ=T&k(Hk z_I7U$@W=h2J%R-Y7Jy&@f+bkMzZ)!ozrk${fcvlj1Peg00KozfEP(%f1z4m^39oZ- Q`Tzg`07*qoM6N<$fO;;&f!f$uLr z|26$=eZKgdO!2c9->XaRbzeVL^ZZig9_#dH){l#J#&9vzaoDjiuy8YQh%q#=5@7t> zm!PVyzIyj=>#sk5uKXz_Eib>ms;cVBw{P33Dk=i}{r$7b%fr8Z{kpQHg~k1Me_vnN z+O=!5YHMTjKmYp|w|3pSRnMNKiAqYI>|_vFQ}65JGh^c?(KUbm)RflN{=FShE-o&v zrLKN_eXaKsmAbIoQ#y_wJz8kQz;b#i7dN-9(!<=Cq@+cXt8d?q4vmjrf9dk&(6X{^ zuU@Aa^?GfaIdS5`TeokY%{_Pa?8}XF z1RMm|z3cMczJLE(W6!>Qzj(sx>-X>6vt!4NW%DCpZ~dvNtSSwycE1%*-q#B4Wn* zgqstmPfuSLA03^YExS`$9^xr;tvaoE!!-o&^Ii1temQ~f&eY>G{kclJA zVb|{6U+wq%1a|cH@>=i+3JPYWrn;^#FD?Cg+l*7pVS~)%pT5WLEPM6pRX%6)@2aIs zm)5QI-oVh5>Zz7+%KqP_OOuYf_^2nYSiRc#`o!#re{%dlW2c3OhK4?K{kUe$nufyx z0Rao{-MjbY$J3{&?&tpq>NF%&mX?*J{oFH8G~Qk}KQHggjLVmU|2k}$oNV;0(QqxJ zLPXsDvn*0NJ6GhLshZyLSTJGJCTD}4C=W<7dw@uHwQi-69-N$t~XC1qtzom2n3 zJ)e8xvGM26pP$LB`}FBkL*K~?6Zdy|Rlhx7{>$j=dD_Cz^e311UyQbtl$6o&6SqZ} z?k@j*_&hH!uiWX>V|y-JPhe=Wi0JL@efH_)%a{85H||`&d;9j~rKP2nHj8)c*s)@} z=4D-#rcYHfw`?)_yGkgE^+{P1w7CzxBR7>?dA0v&)E>ltxCQ3Z{zWxXEzVhp(#0C;zHVZeH z{o~(3Ep2UXadGj7KYviYDM(+_CEab<;&5n`>pNl_)1Gl*?612TF#n1JHGY#+SguQUXvo`&Y$1D zZ{NOv$Vkbo?CirIJ{0WOy}SGRx9{Jb^YYduHYcQp)z#JAxP80ZxwyW5zEQ;F$&*i3 zd3&E;{q^9%gDHDAZ@#?2af4BIN{R~KnWs-vBO)R^B-gx{8@y%P)~#QkRaI727S(S# zo_a$eLNYioP;lM)^^Xtm@bI*}eEG7xdFtG`vSwyxht8ezlaQCM|NN7Si)+&F#k>`V z*$$qXarEd>3%%L1XDh0!tEXG{*| zrE>l5l`A!EY;2BPU%z(k(e?md2^MYTzP`SHQak$pxIDk^ej4b+AF~c0KKz6IVjFkU z*VOmN?4;IY1pmFh^81VZrdO_Cm)7C9c0KRH`LkzL7gpt8w)++M`P3<|qPEq0_udU~ z+_3MS`?n2gX=#(P+uGWAL|9(`mt6Dj-@laF%*>ba@+%owUY~CI`s2rpiM-Vg8|-W& zX8vju#7ts638f_^6@?A@-=}}$5L1X?Xkz7v1WD=Sa!3VSXLM^Wf@( UHcO>Afw_di)78&qol`;+05jE^9RL6T literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Password.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Password.png new file mode 100644 index 0000000000000000000000000000000000000000..9dc9b4e72019be9dd9d4cc97192cb706bd8f0904 GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!%{kbBU}y`} zQRzA6BOxOpQ!O~bfWd-o2ivMBm)O~_Z9fV*eUdKvX)rxCQj9_Ap)x}gt3pIW0waeQ zkN~lP0$?_W7?_Pk@_;?dYMs*tJkAlbqlRp2L+#;@P zHs`l9+xt$gRjTgLiuk?nKHr~hx!*e9D6UGFTmSewvwh!Uh?MW;JA5^<*CA4(u7bbz z@t@ulvuho9<-FVKo7lf^U^vJmpaUdWxE(eyuyBLf0y76Hce}Sj@nI~_Wfx*V$>FVdQ&MBb@065WmJpcdz literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PasswordNumeric.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PasswordNumeric.png new file mode 100644 index 0000000000000000000000000000000000000000..d54467b70fccd91ee93b4e2d5fd1203eb079b614 GIT binary patch literal 1171 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!%{bVAWUc!W8wLiJC{Gv1kcwMx@0`}o&6PP& zcxq`(*OOU{JD-LbO_*pDP&C_6EGc0@jG9`I$HW-5Wkv>ynl3#8JB#qF%z1z&hBxSd{f{{^B zX<6B;$oKEwT{(QX`PSXLp?B}z)zZ>BWmc@FqOxM&KD({kw=aM9{{7bGW@b|hixc%M z3K9Dcb6jyR;|`09n`dQjUvB;Ww|C?jpvpyi_x@Ec z;|VJ%*&@06_3P}b7cMNAGxUk|J=`0|NX18{rvg!=C01pjd$l1HOD5E*3_(dK4;#%G{feEO5+Hi zr2XDldu!|08;k#S<`mV|)LiMGYMWX%Gx*-YlC5hKOG-li-#U@RcJNcuh8_=zC+Yrk zANx5tG(<&4UhKEFwhn&y@Zq+Zmt!{^JAVAD8LyZz$2EB|otYOaVmv)N*FO95`SayO zp~%R{Rok|O#m2?WdSBMo(gO0!9#Ng0{hzQZma{%S_1CYe&xS?(r`HwN-C3J& z6ZfreBS@9VnkiF6w(i-pCg17w{7;*gpZmFD!-jypd-lArd}{b^n_z_Pa_!ZtS699J z`n41kpqICsdT8|UXUfaUzC1hQ{!3RGY3a+G@87ut4nG;4oh$R+R87~O`{qqf^jUL5 z!-eHLPd{hd&o%AL`6jl5MHw5OIG-&pF0R_PeY<&RSXkO_agTLBQtW>Ik}iM#=FOWI z#XyNjV0ioSUi=IL)?U4R`}9;%VEz=) zVNi$wWmGuhhDpSy+J`ol413;oe*=m_^Rep&hMM~cj18hUt}!&!Mld*RU}#8S1nLDc d9<=XgI8!z)`;YeeVqjsz;OXk;vd$@?2>?{+JU9RV literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PersonName.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PersonName.png new file mode 100644 index 0000000000000000000000000000000000000000..2f32a92c9c76dcdcba14dcc91a65768077c0a8f5 GIT binary patch literal 1911 zcmaKtc{JPU8pn}qsn$*?W1kjdr?sn6TPR{_nc6Z89VA+{L`70dI;f>Bqn4sXi(+go zO{JA)w9*P<6bXW=s$GN-f|{RuZqL1c-GAQYyzlwE&-;DO^L(?Q?oJ}Y^1?hkJR%Th zdoLayUL9ancO8)zMp2>g?Y&L8Rd-CX%`KtsMHd6m=^4WleYFgjA(< z?Ec@uE^D5u{O)W2!$mne=M{d}Y3w#U`naaXajFZgeU(~K2q`#i z-b?toz1##*dInC1ZftJOZLdyj%u!@-a@NYr&Y`dTe&S>ZD!1GsK7XXamjW=pY|c|R zRwqnvvKQ{d$Dczw^OC$NoUZccm3E`ms{>_PVPRpB z$@GQ6stZE^qOwETGNI7|`J8NSjpq7vL{I({NJxkeY$>B>VmMPwX`Sp&^xpOdfYX2I zJha!5{!zR!!4@Ay(~B6aw0)aOfRXsLw6t2`hs!j58Tw&R_xtdJK^o!^c#ISz}&BL`3k0c7uhWgjlfA{b(Ypnn zw%l8&Z4|cvU8J{GPb&%_3z*Zy1``f*y6Ep}C)Xmqz#lCw{asvL-EJ`y(d1Dno?^{G z#L8)bxPv_obB;AjHVW-I5zk<=(3woXO zVSjh?60Axzb+X1yffD-d+kt-|xz4kCI1%5KA*Ni)1te}DPIMp&Fb7-+bL#aIJl=2X z!tPV=TE3M#%IRx&F^MiDsg*ypydUFmc7?>GtzPOt>mA-&6WsJ{_mO@UR&6GT@!__^ z{8O$MEzSC0h~6D8EG(=S9Y`pp3~tFa#4nHXZf$<;H%6THsDSqxhBZ-)jg0uXZp8+q zVQPsnd3#(+O6p+A%gbxOLPu1|O3q-r!Wz{lbsmVz?IyLt+6~HNyfm&1p6)`s9pD_Y zLzF=72zw$qV|sbZLZ{)Ze!D~?%q9(Zs3ZXbf$(mbo0~5Uv?cFuWP)gGRu*v!uyJWH zxbz0Y`hG(T#aBfoo_IED6dT`nTvo5x1SD`msLn~$iFQ}c@UK6bgNZ?f2m8C;`2_{K z>~O2*v#qaVRc$Hg~i3TSt8fyO$8S|gAw;kb25ImYiM2M?5v|+2bnGHRVeF{ z?9^Cqv!pOt-31yR^$Z6@xHV1!Up21MoK~Xq#WpT_Hux_Q26R4mA3G97uJw2niB2a? z(sfC~G)Fcnd8gc5M{rgxadTs1KR>_J`07C2ueGwN6Lp^I1>QmqIw0g4UM$^mNxGy&5RS3UbPS zm7bmIjHfgfwz@0@6ETxkrT$yNgoHoM^Csh(KfXclZan!3&^6#Zs?o&e_zS7>?cDOS3%uV6qa(GzShf3RYoFu+j zb!ZMKze^LRT2jQc9~t)Vvu2&ViJ@dsUp^W#rmAABzpu|HTQVlPrFQCfqi6=c_*TgK zr@0G2DlPdbBs@J|9Nq)UUR@bod=4M;s&8mG7+0@M=2V)C1YB$mO@BIx(TA6fkWlOe zPa2;rK_E}rMrkS)aMFLN}Db?v#QgD~j}kFB_ln`y|_V zZGND94roJ>$}-$vUfjwC>*Cs!1oz%tH$|~N-|j`gsNl&YuSK>-twvyz-TtU&k3h>_CcwG>%+G(+?|d2l~$pSk95#VAC9gR1Lw6 zK+pMTh83qBtFk^apzqg@TtVCmd9;0%LXj6z4aflQf48WA0|C&z!=2-DvY{ystPNAZ PPw_Y1=F literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Phone.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Phone.png new file mode 100644 index 0000000000000000000000000000000000000000..c06c73eb1d263e6759a5cc82c4b2c870be7dd546 GIT binary patch literal 1806 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PostalAddress.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/PostalAddress.png new file mode 100644 index 0000000000000000000000000000000000000000..093524da10686d232dfdb893e06ab0d205e48326 GIT binary patch literal 1971 zcmb7FdpMhE7S9ZA(4n19F@~k8eH2kM)gbPpT7#k&A|0|q8)lliH8evKrl`79%&<+H z2{N=UlPaM@s)`1sv}mZfglL+TxHO0+5+dx^?Ck!r&$Ii?{_&pYeD8U`?>*=Ie&_q; zo(}ZU)%ijP1On;$e&c->1o{X9_++h}fV~*jGzU^4*p?MJT-qmKxy_g@x3b< z=I#3H#czJj@%MZF6Kt>5y?v{me)~*M7xCZj^~&WQ!V1k@PiH@eTq$5fl^Prsajd?{ znL8mWA+D{pdOWTN*Mnmo$Y50D;`Fzebop_5t(32R5_}{$%jq2R(9|Fk>epI?@VM#Sfo$ z>__0`O9dK<%e=OlsAqW@J2vmI=s;AurBWW->y|3r19{W?3Fq&9#Uq}YHlcO<)Q{!I zZye2#&9U#+oUQZ&-a)V~O+8AK&W}_(=}{fy1CO&?aq+B=(`r!zcfPXFJDvm2858st z3TUDAe?x0)&vxmb62$iXr}STU!puyi_k9RpZOG;1{8)dDYI#eys_hI(v1H5Y^Fcx*f&JkjiljudOar1(rIqRZ6*l=ors?IevTDL<u0@LB2?ehc*6zzxDd=J{niMc@*z)> z!IALKX(&GDu&ajk<0gY_P0jdkf!_ zx$d#0ut-}Ao~+JOgFLq(Ta@$xBz;f=kows{<|*?p0fr9T3E;${@$SL!Bz00PJ=R=I zmf}>YGc=7S6(@pso8EN3`VJBG`zl3)Wqn-HUF&L@qa&WfloSX2uWdJ(%y%UqdAFyjF5fBti*I+f>Z0@Vg}Kj4TU^Hn*6P z;9^uZeSK6i-HI#h__p|6SUVx52Q%ve&Irj{nSOdvKSgmi?udO~YGuN%&?IyUGj6&9 zKo?CE%2sDzBUW zS=!HRjb2+pcCS1+JhhNzx0MZE;O89(M`q~@D^*R|gcz(YJPIgR@=ML0g%xM>oZCl` zc{ImE5kCEE?&67umSx(Z*Uamx155L&0;uo>!_E)*|5r(QY7A2U>HlAO_zz*>fz$%^ zKgCMnxC1lJh~$~PF$+D3|3ld{{TV;f91)=H-DD_;6A9?nzqD#w=IBlFE=oygL;+$9 N@;wpgUFU_$_y>!7#;^bY literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarHorizontal.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarHorizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..a8e3754118df2fc3bcfd46c454195ac8b7860bb8 GIT binary patch literal 929 zcmV;S177@zP)asBOJBNhqKE@m5pf}+Ac%;93&lNA+;zWn z?}3PWqgMZq$KU-fZ52_G9O8Ihd`R0gd2t+H67D&V$KwGJ(O-fGfruC^A|eKhh!`v) zA_nWJplDvnql)Lm@AjkfyuxEf#9+D14oiUyl8jD!h*V97;?<$*eyBbJ zsy_hL2to~np#@E7p@>jYcof9nRlngxjL{-uu!;{A*zkOIki1XDc_>}ny@J&$lh zZrL?d!TnJ|K6t1^IIyg-__Y?ku9wC=nIuKMz(RT05_cXx;oOTGqaM zKaSS17rzuOo@_)6)^7_|_TVE}haMq&_=yPCv#*2I{F=ccVz7R1u&h0|VeP%^d?ozZ zC#>&%Efk^pCRie3JlTj`2v+rwDfpAchPrInRLAgXh>e);7&!~^QB8=CnT`0^IY^9~ zi^TZ(NKROYK1GiHX%K4y?ib@cr;AYB%&hmDxus~IadkoU6s9`YMU|0tArKp6Nbt-jA#vvSX#~( z0<{eYrh6jP&5~CH!#(=I%=Cw84S?C$7oj>!ye0uHT*9k6M4UCaF%)%{>TO#r-QHsP zp%en9213r%!5)Jawpdy4&%S@55tD#9;jixAAzsxQ(a% zRvz)F@;*W$28)OoEFvNXi-?H9A|eKhh={==A}Y>jg!R05cA%b*00000NkvXXu0mjf D2vNAu literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarLarge.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarLarge.png new file mode 100644 index 0000000000000000000000000000000000000000..b33895f13687c22d3defc2d08e56d3fae8ffb011 GIT binary patch literal 3845 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 Hu0mjf!-xxL literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarNormal.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ProgressBarNormal.png new file mode 100644 index 0000000000000000000000000000000000000000..d97e1158f44da9be6641b5c7b0739087919cbe0a GIT binary patch literal 2474 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RadioGroup.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RadioGroup.png new file mode 100644 index 0000000000000000000000000000000000000000..14b3067ac21b74d7f233583c5c3ca90378660730 GIT binary patch literal 1874 zcmZuyX*3&%7LF|mwJVyUmX58K+J;JORZH!3Qbc1(FxDbyh>rFV8fz@6U}7DNB0;4S z`)JFwL2Naujio518fvXlt;y?oKi-e|@!k8KbMLw5+k$K5_=Ok0@a`D_hkj z^$=8J=)&$~wReuep-PyXv`@GU03Q}5^I|~GzC?q3uI|4{@%be!||ek>@}yAEci8p zd=dUDoOA+Kkh%*J6q6DqG$3_-%{fP^D zP_{NH*}|0=Y&#U%#WQ7BsUsN-VG=>-sT7^lgDczX}Ubs*R!BT#; zQWP;WI4d30R9`av7|W1V;qRBYa6LSC%L?ZrE?#lE;#N=V6+$J{C1gIaQumkG^7-EF zQ+zk~zAs;tFDTeUkf*;+$z{HXf3BnC9o9(#@2QOaHRA^X{SCf z+yrO0Wn$R>tKC>~9AVx6+vP*8c8$1Bp6}XOzRxY6ohxS`rh7MIwPNQm$rai6W~|fk zhZ&f;3EGmCdmPe|84&}!aV*`Sw-}>6DrYd&!jc0*B2piiYg}(MlD1%iguIvLI&bcTKiAlv4`z2@DQ#X+ z=H!n2|IRYo^b*oN?py|IcUv!9E@|HiBbpaBQlvVTzjUAF}L{ zNqI36B&b+0vt|h%{r-}w#Zg79PCiyPKb_km=-tz@`2}s7R}sjLHB}RQdVBuUC*xJ) z?tRGB@#v^1tSUpEdy{Un9V)1%+BsWfhStDF@Ph@9;pDyYu^Bbpcr&Q5Gza^|Dou#n z!EFjXhBSg$=Ggjt**hRRoO-?W+GNnYied=&6nXlNI*er$i)Po+#cKQ25?m*SKyMh% zNTxMm5+&%8@V+(3;Pt+dL^$F$_mVowHx#TwFCaTk0KAy+1yAau01L@PV~4_!s~x00xU&KJ^iDDUR41MsMXwJ`?yth9ZC1XbM_nCSWiaCE_n9 zAlQLtkm0$q`@bxi7+SVr z#@s~&E?&i#vGsSzd4}WfEPi}RrAnw4YDCCSArOITq-yKx@dDrNs7}Qw!8ICnq6)i7 z%QtH&>Hzm3lufgqnO+A<;;D^aA6Unxfs=H8@b~v$b+PM{EtDG{b@iXiobTIpS;Za50ZR;xbR+A1#z5*!swo!><0}hfDN%N^?{KGNznM5L~{kF z_1_{dKlM%sa8Y;Zv7|(IE%^PtuH! zmZhE1^*wv8N*8;jz-b-4DdJvA;!8sR#`t#x{x9Q5_ylnHc5uXfoteY^l>i4@SDR+* HfYg5g@Pl-+ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RatingBar.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/RatingBar.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd21ff2e04c0da02b2aefb098badefc73b305a6 GIT binary patch literal 3870 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 Hu0mjfDSfvV literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/SmallButton.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/SmallButton.png new file mode 100644 index 0000000000000000000000000000000000000000..afcd066810e929ccca9ef0bfbab09e188cfb347c GIT binary patch literal 1026 zcmV+d1pWJoP)C*UD?jH%*;&L-{04IdwV;fe+T;U@lgkvo}O-5FDfe1 z`swK@p}hf}mzQT*$Kacro29X_(KNBc!$V0;O_hm>3AwtulGoQ)IXF0whK2?`CL<$5 zW@l&R_V!j@US4E#b5lx6N-Y0IX=$mft*z;?_xJaDuc)Y~uov{$*q9D-Z*Na>a&p{W zSwp|9K8+FY)1=ZV$U)|&EzgM*IR%*>4G2HM-(tNDe61=H``+}vos zu&~gP!)i9J8e47e@X@H6ni|LM!w5{YwYBx99fzxlWo2bKYIto`yS%(Kbx4XM5#l^*X%y;Mcuc7fYh(Q(<6u4|9s6RbDc^%r= zU1VoxTecZnL8C7ks|rto&NZy^@$vDWb_?EuK07tZrM~49m*OWPW~LCkk-1 z3T*c}J3A#dHrB0)c?yj;xvQ&7j*gCWhjVgrBHi8Hx~h$qh8>CRcOCr4KcNXtXa=DP zO=v1KIqEP)}N5ij>N} z{A=?v^KviuioKQBjlFjSIp;Yu=Q*Q9B9Xu^HIbM|OeEHWwcBknxm^Ag{@0;U zD8TJ@LoSztMxz05Z*OpScL)3X`!G8@JD9{qMn>TH_?R3wH#d+>CLt6G5vkYLSHicq zw?QhE4i+)oG=hmlf-=XQFflO!#bS~CUaxnsh&7u{0>{V4y9S$@nj(LtQW;EQlarHO zgW=$%r6q8=T)aT#av4TPMDwpw^z;PPY85h>3-1D`I#`M)7d*QjYdPKg^rJp5BgqSUj8(L z+(7g5^E`ZOYm4=zQYoI`_z0Sk6S}o{wIv%D{sn`q)BF43`u`w!v-Q8Wf8#n=L z9y9yZ0!pQl^>xM_9v&tfpO8+U*=&Y|g$3By*nmJF0GpeeUE>HM#x)d&LZLvDB9X|K z3*hh1h%s4se}88&yccC7MbUOt7iQo#vCeFfwB9+ zE=VvjZXi^lgM$O=74bc}zP={>>gtNune>a8-|r`^R;$r_7mvqDHII&t=;=Y<(9n=D z@tB^ThIBejfsr7V-pR=ctgfztTCM)p$^DcV9_rfK8eCppk^*Dfw!Xej>dIsj6|?WE kDE`qDiHXESV*eGfKlf6@;qY!mwg3PC07*qoM6N<$f{#>$XaE2J literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Spinner.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Spinner.png new file mode 100644 index 0000000000000000000000000000000000000000..5f86de9c40ac33698b2c96f15c47af0a32163358 GIT binary patch literal 1267 zcmVYRyBxA`9$#lV$Ar~SP;mQpq$yBb~$Q^}{l#pb~Ovo5A zkMF;C)!v=|IeUNKx4+|aj(Xnub&j?6THD!Yucx)%_3UF|VPQc40PsV=MF0RmumAu6 zf&~D8U;zLC1nVo1A~iJ?Um5@qEbTZsIZTXvW_<(mY0`B`M|({ z;(3mbk0~T11UDQ2rVuO^7@jFe!LyU*=4P?H;@Q>j1gog1$e@lz>iPLu)K^zmYZ9!2 zf&zp7!o$Pm`rzPTqubTg)QGaRwKW3)jEjpCbv#4UT_#JBmzRf|4FFU6ufLqmhe(MZ7tQvKQ1?*?#LS(&K6yu378u)ew-Zy@|hBqb$5umJc8 zkLIv=@p4Z}M3+70?f_LUP9v>ggc7~-T9|gezz{G+j4P5q7sU4G@oh^=GpOTgV+|tq_C-Kcq zuof2=MOjl*69fx@pCVXeV`E|v@~hg8U~6luIA(u;UvU5{d7K;_9fco?qpPdS>;$W^ zu~C#A9UYOat*xs641xuK83|TYRFs^f8Xg`NMpCJcy-6h{B_apKQCnN9>VIO#yj1Sy z=0<~qgQAZ6*8jB!a}X@Has;a7gDm=!tW19o#*Q7k#>guX+xJ$v-2i;i~ z1PcH&*(GG7Cwr1Ox5IfYHchecB> z6Brms-QC^7f5xAgg_|F}VM_)tYcazD;D^{6kc0*RK(GJ+0D=VofM7we000my000CF d007LK{{X?x3bA%ijeGzA002ovPDHLkV1nt6X7K<3 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Switch.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Switch.png new file mode 100644 index 0000000000000000000000000000000000000000..4e7a3dd4889bf16f8938579bcd32bd7c7448f950 GIT binary patch literal 724 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 Eg1qP)%>V!Z literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Time.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/Time.png new file mode 100644 index 0000000000000000000000000000000000000000..3a53fb2e9a7deea7a1b94682c94bae6210bd672d GIT binary patch literal 1559 zcmV+y2I%>TP)q000mc006=Q0E7hqfUp1n5EcL+EC2w61pt7s003bD0Q^sc6&@b0 zl9Q9wmMvTO!2w`(39F{2Mm07zs=mHH_4VslH9tSEsj8}SD?U0pTAe?CUdK;NOsL7p zN%iX0D|PA8B^47Bv!rWUw{D#}efqTO>gv*C{`m1jb#!#7($Z2D5)$IGSO8e%!ZHM9 zi#x*FwQH9e9UXN##>mKs+P;0eN7o~g6ZttCQ$!RM6=iuW0QiBh&Ye5A2zP}Q8yjoN z>ihTa>coi?Dk&*RrKYB;^73-^>(?*cHZU-tf`WqFx|TI-)~F{>p6EDvQj@158FTB_ zt*Wf7%pCLabkwb8~Yoiv@sxTv+ntB>j4NdK|XL$H$vvNsh~%x$oV(r~7~W_|f50ndG28efp&P z+`W6(vRDB4hlM3es?N?%_2R_~b@Adwhke4r!pyNG0q@QnZ{NPvpFe!~(COTd9zD{1 z1_uW%i#3Rgi__OC-%AqqQ&Uq~%-649SBZ&J#K^Mr{rmUo>eZ`i z{rdH0|H8sT)z;Rg#~<Q}^%RXGazgmam_%T#=cXX^wU5*fF=}kbh$N{N~M@PRErt z=_7ruiWTe{ty4%@$c`J!`e+~9z) zR!CS^u3XXM{Qmu0ZP>73QQPa+uQih7_jGP)Gx}K-yLt0wQ+OXfd{9S@9MK8;ZQHi# z+?NQ&*j$K=jC45f+}xac{`|Sxw{M>wPx55_{rzTpOG}IXd*j9pE%UUrG*wYiq2uK9 zrluxta6niqAuK68mF1L-BXwR@&g~0fE!-X5v15l_oNO8x?Zw5#4(F96sVswS^LQd` zqfcF3o!!{AwY9o!c6L_Rv~iOI!dgaQ1qTPK_V#u?#^=wU7v*nOtFYv$Npe)q@>C1+ zag~*o9?jd@+G_UMxpSvo`{Bcf&Gwv}9By(zSj#D_g;F?h;DF_G`$AaWT$`(TZ{50O z_7R!ewr6E!neCF0=Ozb)wM@b~e*Cx@FF7n<%jrt=IL3(=n zlIJ#xKc&FaRq^MWH*YM9l_j8j{_Wd0wQ18POLJHV3lP>S5tbZ*G3tw?p6KAggI>*T z9IuhxMMq1@g~w~8uT`-|=|O#cy~FF0H#{IL06!O2b#=AbUzSzg&b{ye^U0GZ?b@Yc z-q{YMH?fAunwy*L;-o_T!Gi|~3&5X+RZ>!7_LUa^F3k5h!ktQYIiqOQEy?R(M1oRr zE@$oJbumUU>eHuBRbXJCWwEj|XndEmXV2=KTuMrcu6Td>@}(LdA2-`=b7Tk$zz>8q zGc)7Xu9~Midh!y!-rioPrIu{t#*Mn&sNT0t z*dr`}6%-Z#0Kx(QgarVAumAuM762eD004vq0AQi84jnqgj{^Y9jtlo7EC4`Q000OJ z01y_!0s#LN768CXKv@F-P=^HofUp1n5EcL+EC2w61px3Le*jzu7BOl1(Om!l002ov JPDHLkV1k=#2R{G+ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ToggleButton.png b/.metadata/.plugins/com.android.ide.eclipse.adt/palette-preview-r16b-15-holo-37inwvganexusone/ToggleButton.png new file mode 100644 index 0000000000000000000000000000000000000000..7961a08c0c91217191495aed703dbe9f79accbf0 GIT binary patch literal 668 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 pM2Pv{4$Qyc|F#i8AGq%?QR_`_SsM%%KHelper 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 + * @version 4.0.0 + */ +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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/0/60866c2216c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/0/60866c2216c3001119baa706e9d70c26 new file mode 100644 index 000000000..cb353f9fa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/0/60866c2216c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(ViewGroup decor) { + 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, decor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/0/a05891ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/0/a05891ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e62f011d45a2c4c61a60b6451bec014a557a5188 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=q&!_5LpZJ{Cp0wt58!#o&?v=m gn8lDKU<(7oW*(8&@UL&}fT|cgUHx3vIVCg!0O}VNC;$Ke literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1/124c97ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1/124c97ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6679cf386 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1/124c97ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/1/408c8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1/408c8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..bb6aef1d069a14a7fc1cea9780c919c61679e4fa GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtXipc%kc@k8uWjUIP~c#3xZ62X z=G4p^oaPsfxfS0Jish)R3f(&WG9yqa14Evg(y_dGGlfCy2iXqR3?>_SEs{VyhV?DH iJ0OaDc|iOR772{!kNsXaOPT8&i0|p@=d#Wzp$Py$I4IEo literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1/43fd8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1/43fd8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..01d681697f799729aa60bcc03878b8718ef5f705 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzFHaZ8kch)?uW#gKP~c&9OkaNH zNWhsXa}P0HP*CC8e>x;QVw%w1wevX{81fiqT9$oZHH(4a215zM2{s3I28IOo7eJ#J d>KPlRN5&o6d@ywr|9haR44$rjF6*2UngC}HDAND{ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1/91a293ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1/91a293ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..81c347108 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1/91a293ff24c3001119baa706e9d70c26 @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/10/0060e76d24c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/10/0060e76d24c500111b2a8b7f47e59881 new file mode 100644 index 000000000..e69de29bb diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/10/10660e4d1ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/10/10660e4d1ec3001119baa706e9d70c26 new file mode 100644 index 000000000..f83ed11d9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/10/10660e4d1ec3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/10/800a91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/10/800a91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..bb19810bc2062509e4e4968099a359ad73818728 GIT binary patch literal 915 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;rX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfwTh{zxw0jNgl<&3j(^ zeD(x}!be9sh1LD$__>xwFX-mty1-MRJ?GVgBPRYo&#phmts!D?ltV3&FI%+a$=z1Z zV;YHl1iMSDgJ+|>#46F---v^ z=n46F|IdfFb=)S0I4Coo@!g}n4Nex)S*)#RZPN@k9D49tzo1o|L;8h-cSg(aGrNAg7qQ^lmAJNnY2BwD zmg$yB$_Kc(9`bFT@$ln4rdg7D8~IZ-f3I60`0mq%qw5167@Xn!BqR{_Lfuy~aYE2x zQ4_Q6{SU<2c z;lT8&TH+c}l9E`GYL#4+3Zxi}3=9o*4J>pG%tH*#tPG5-jE#Y8D+7a&|KB#FXvob^ z$xN$6(O_z2Y7RsY4Yp<(!9Wd?ARB`7(@M${i&7aJQ}UBi6+Ckj(^G>|6H_V+Po~-c P6)||a`njxgN@xNAiwS~- literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/11/308173515bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/11/308173515bc300111ab8b17b137f3789 new file mode 100644 index 000000000..867aa1532 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/11/308173515bc300111ab8b17b137f3789 @@ -0,0 +1,143 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! +// TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); +// // set the above and behind views if defined in xml +// int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); +// if (viewAbove != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewAbove.setContent(inflater.inflate(viewAbove, this), null); +// } +// int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); +// if (viewBehind != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewBehind.setContent(inflater.inflate(viewBehind, this)); +// } +// float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); +// setBehindOffset((int) offsetBehind); +// float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); +// mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/11/600d2b0d54c3001115d2d454e05194c5 b/.metadata/.plugins/org.eclipse.core.resources/.history/11/600d2b0d54c3001115d2d454e05194c5 new file mode 100644 index 000000000..c6ffcbe53 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/11/600d2b0d54c3001115d2d454e05194c5 @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/11/90cb999352c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/11/90cb999352c3001119baa706e9d70c26 new file mode 100644 index 000000000..4edc6d6e7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/11/90cb999352c3001119baa706e9d70c26 @@ -0,0 +1,19 @@ + + + + #224894 + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/11/c07980e02ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/11/c07980e02ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..744d7dee0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/11/c07980e02ac500111b2a8b7f47e59881 @@ -0,0 +1,155 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + /** + * + * @param i The margin on the right of the screen that the behind view scrolls to + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + public void setBehindOffsetResource(int res) { + int i = (int) getContext().getResources().getDimension(res); + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/11/e1128dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/11/e1128dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ed4ba34ecd9f8ab8c557924fafeae6a89307bd7c GIT binary patch literal 2851 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 BM!Nt2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/12/9062a79e52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/12/9062a79e52c3001119baa706e9d70c26 new file mode 100644 index 000000000..67c8436a6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/12/9062a79e52c3001119baa706e9d70c26 @@ -0,0 +1,21 @@ + + + + 48dp + 48dp + 56dp + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/12/b1f093ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/12/b1f093ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..5300dedd6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/12/b1f093ff24c3001119baa706e9d70c26 @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/13/00abe03af4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/13/00abe03af4c500111689feaa37e8ab14 new file mode 100644 index 000000000..f2cc7b02c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/13/00abe03af4c500111689feaa37e8ab14 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/13/01618dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/13/01618dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0ad6c888b4c7e436e7d7c78432dbfdaecc95a7ac GIT binary patch literal 127 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%Zk{fVAs)w*fBgS%&%9ECxB?U?=uVx Y$^4u51wHGE0Gi0)>FVdQ&MBb@0N@ZURR910 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/13/50ab3dce27c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/13/50ab3dce27c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2b6c9b5f3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/13/50ab3dce27c500111b2a8b7f47e59881 @@ -0,0 +1,32 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(context); + mPrefs = p.getPreferenceManager().createPreferenceScreen(context); + } + + public void addCategory(String title) { + + } + + public void addItem(String title, String cat) { + + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/13/72e390ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/13/72e390ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..2e06dd01be8ccbab90d63cbf47d13e905aed3e20 GIT binary patch literal 970 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;rX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfwTh{zxwOjfK$EgnR$;T z=N`Kp(hSrM@CU%evd=bf=-4w^bQmnuhmUH-jd<6WZ; zHl4_>Rk2U@t}L_t|AiwlQ891B3C|YS1B^O3M@oxo5*z)LB91b?+QOQX_r0yH)YX2= zvK_aW4}ZVF|MIp0)1X?{@CS{e_APBtKk;H~nV$PVB{N8HV+L1tOj6 z``KDz%d4l`HAyHPxAByb%b6xG^S8m<-YfXS7v>b+zlZNGcwheZcvv-P0dQ7=MviH9v^t)=yc559VF`j43j z_pMt2oAX|`goy_Fm~UMa9d%t_^^2qU)cXl;U0e%IRZSM> z>7Ksk_VioOmKv*1mN|c~ELg&~mMikt+LpAdYoES)QG3#uo404uV`0ytJ&!XS^rKz< zU6j9{ob*(;{k73gyQmwdmG2d+82l2_J(5-Z=Epp_^THpe+eb5HIvzUo?fW(va5{7P zd0GD0trC|9zjsRjleub%YeY#(Vo9o1a#1RfVlXl=G}JY)&^0g*F*LI>FtRc>2C}UT z3_|{Y+l-q7HAsSN2+mI{DNig)WpGT%PfAtr%uP&B Z4N6T+sVqF1Y6Dcn;OXk;vd$@?2>?&0tquSH literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/14/02618dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/14/02618dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..19b50abcb536602cf2cd36d5a19805464988bd20 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%PM$7~As)w*fBgS%&%9EC + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + + 64dip + + + 45% + + 72% + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/14/d0475e0416c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/14/d0475e0416c3001119baa706e9d70c26 new file mode 100644 index 000000000..cf2739b7b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/14/d0475e0416c3001119baa706e9d70c26 @@ -0,0 +1,1158 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/15/034392ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/15/034392ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..82f752fdc28390f1dae188e66886f9fee783b4f7 GIT binary patch literal 602 zcmV-g0;TXoV&|>P?2N3a|H=XkIpb%g2C{mUcD8z%K5!WW71`A3B@}P?c zNzmeTUM-&`=;A@rh-=e`Ytx8p(}-)+h-=e`Yg0e*Nfwct-zMuNo?gfN+FNCOm6(Rs zNBrh8;rK_F^Mfu~8k>e2?@WdCI_7lHVR+IZj_>A~;=j0*zBpPVOJB@8&9C^w(v!^i zcs#`4qjGbZa60I4akN%e8hjOBptPW0e8JL!ZgC5x1-;^yN((y0EtVGC7q?tma9i9# zX~A7_N2LWf#T}Lw>=$=jTCiJOp|oJHxKe4sPI1N3!s5l1OACt?_fT4>Uffe@p<40r zRpP6(P_6jSy?2bx-x9}n#O>6o(Q^BiC^BxWR1^RB?JvEr|0>Nj5k)!eSD9&8HSzXK z2sbij-vth4?P;pL%~0mos(Tg<|DAn;kcS obzts&Y9%t@53qx{hWg?AJqc6disFjI`v3p{07*qoM6N<$f` 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/15/10e44a7c48c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/15/10e44a7c48c3001119baa706e9d70c26 new file mode 100644 index 000000000..eca4201ad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/15/10e44a7c48c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/15/5049ccb55bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/15/5049ccb55bc300111ab8b17b137f3789 new file mode 100644 index 000000000..66b255f92 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/15/5049ccb55bc300111ab8b17b137f3789 @@ -0,0 +1,139 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/15/a35891ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/15/a35891ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..eda10e6123e1e1383c4617228ec0c96680d60dc7 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn1!PZ!4!jfu$#Gb-B{xqtMx1s*(O%+nLV7IxRdaaX6Iu&3070|zpW ye6d-ZyJWwc+pgOl@x443T>9p%`1p8cx&%YrImy|zOvgZGF?hQAxvX$jV8FrZ@J;?q zbcL8uwC8*^`8m#29p5Ib=%`p$wC&7oqt#odO)b{rdQv>$UUk^Hs0p4nJ zaCd?*qxs3xYk`8+o-U3d5>t~6?){q5*x2~c-l(n1@K5>ymj5$1a2Oc?!34d7Ck`Aq skg(^gW|wXH-lZoEvTk@AJm}J3sQWAGentL}KF}BjPgg&ebxsLQ0KFYBT>t<8 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/16/40b72d9993c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/16/40b72d9993c500111b2a8b7f47e59881 new file mode 100644 index 000000000..deee1d672 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/16/40b72d9993c500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/17/42df92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/42df92ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..b430032a1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/17/42df92ff24c3001119baa706e9d70c26 @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/17/a1e78eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/a1e78eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ea4ee042eaf5cfe626639e5ce1bb4e5692e6e5ff GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^59s(?*`6+rAs(G?r#o^TG7xZ`zf?Wo$i4qI|8=SuS_>z)W_YPj?%Q>u zIp@ANM{x}Zqe@#*i-Jc_;!9;KcT)!P=e8Z65pgErb%iKSkCNb@A?yTt$n@r z2c`IHF%KKu<@hR|E_CSLV|hUMOZy3b87rAYm)KaVUb literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/17/c0ffac6d5bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/c0ffac6d5bc300111ab8b17b137f3789 new file mode 100644 index 000000000..e3d357452 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/17/c0ffac6d5bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/17/d1af96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/d1af96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..510b97488 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/17/d1af96ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/17/f11b92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/f11b92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..9174c4e4bc984a89e1ed643bc66b1569466ef52b GIT binary patch literal 394 zcmV;50d@X~P)pS_@$ zhD#gW|+S$zvH?tjZ06u}I z+WCj@MGelS_rM46*K*DD;uob4z^?VWsl%^ISMTdf({7b>={={?i$=qw;%iE~^x|tv zyVT+%O1re;qe{D!;v-AD@ZzIOyU^khrCnI@sM0Q^cw}ieym)kJH?(+0X*aBRR%th+ zcxGw0x_EYJx2pJz(yqJstkSNlxS72&skG}Y{tg(Y7u%+n+Xa4rW9?Ay@Gs!I^V*st o@Ei2q)9D9V5fPDPZuO7v|4Ms3SH1lZVgLXD07*qoM6N<$f(F>P&Hw-a literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/17/f1fd96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/17/f1fd96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f5359fb40 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/17/f1fd96ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/18/53248eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/18/53248eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..986ab0b9746301f2dd9401829da09e00995621b3 GIT binary patch literal 78 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1|-8Yw(bW~qMj~}Asp9}6B-)+^BAxRtXRm= az`@Yw&#rLZUbzUUfWgz%&t;ucLK6T(%Mo}0 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/18/b0e0d3895bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/18/b0e0d3895bc300111ab8b17b137f3789 new file mode 100644 index 000000000..1901abde3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/18/b0e0d3895bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindOffset, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/18/d0b0605522c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/18/d0b0605522c3001119baa706e9d70c26 new file mode 100644 index 000000000..6917b96f3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/18/d0b0605522c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); +// layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1a/0080b4134dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/0080b4134dc3001119baa706e9d70c26 new file mode 100644 index 000000000..eca4201ad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/0080b4134dc3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1a/4007eefdf5c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/4007eefdf5c500111689feaa37e8ab14 new file mode 100644 index 000000000..23c816d84 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/4007eefdf5c500111689feaa37e8ab14 @@ -0,0 +1,12 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1a/d0092b01f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/d0092b01f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..42d451964 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1a/d0092b01f6c500111689feaa37e8ab14 @@ -0,0 +1,12 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1b/735493ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1b/735493ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..8811dad8d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1b/735493ff24c3001119baa706e9d70c26 @@ -0,0 +1,40 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1b/d086255424c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1b/d086255424c3001119baa706e9d70c26 new file mode 100644 index 000000000..10bf2fbdc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1b/d086255424c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); +// layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1c/305e0e93f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/1c/305e0e93f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..f5249830a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1c/305e0e93f4c500111689feaa37e8ab14 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib.app; + +import SherlockPreferenceActivity; + +public class SlidingPreferenceActivity extends SherlockPreferenceActivity { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1c/90be36fe0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1c/90be36fe0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..2383b70e8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1c/90be36fe0cc3001119baa706e9d70c26 @@ -0,0 +1,779 @@ +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.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 + * @version 4.0.0 + */ +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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/1d/223e8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1d/223e8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e029f210b9a81ed4765d31e90b6e49dc8aa37bed GIT binary patch literal 1537 zcmV+c2LAbpP)P*hY@RCILOyI+)4*Y%ioMH6eaT8-v42qXrI z0|4iGEk=d4Xm52^#H?WUz%bBygG}I|;L!cJM*+u%I9T*&&%x@0sx#0Qk0mTmeRX1h$MIxNMY&% zsz{Hz01C^N@8p~dFgXbIRub%{CUOKKzAQ3rfl0r3M&j^DZL~BnC0R+zNTfH*0>l>% z6xe!^4oO*vg0sbY%(i4Znw@-;nUbs&1zN~PIe02zy)Qcz&8uA?+OU=`?e2Zs5}uJN0M*6C#a{)YX?>^k&iO8v%U{pV&i+9YXUL@sAe1fQs10%V6ikBo z^7Qod_s{$xhgN}Tci-i5`3pX{;N4;1Au(Bm7x@)z#1I9LmdL~RrF4uC5rsHs>tE+w zbjvJ)LKv+{MYbuBrU=TBLj=6Xm=@t7;baF+QjNr0K02$09MPPz_Q^dZ5CLh8#Oov4 z0!TsP8|Jz<^->fRi@r;w5OrSCkw6L?N(J|#V;?nA78HxV{Q97DD=gWeOHxKs4U)p3 zSoD>;waz;geHn?ahed6Tq%7rduPgn zV$nDE$&ajtWS5-`4=n>hvFJNE&bxxNGnt2!k)T-g9UO0!_0BFb6cm%bLuC>qYeBK* zyN@VHxuTkNE#cFa@PaJz!! z*)p0eo;YjAyoc}Lcn`@)ql2XA#Le!l%y)3C`#|D`qk*LC#Leoh&{v9irz@IDt(4j|E-ey3YJCdAoj z17Q35`nvale)TKB+I=4%AAxk%w!OMGAf++t+Mb@Cemp-vW4j&J%V|A%#TR&cd&9%S z1Mctdf1tZ-6W>Id5JKwGXhvG!+}wOSKR^Gos;Zyq!S}5X*>+05G4|7V9G{hQ?!VjH z+iw8YkTX)YMrymYx~{`?w$U_yh$q-O1#m*zu<(hQDx}lJ70s)V5Io{ZN7v2rMwVC7 zhTm_2@1*&pTK&uP8_~o&lye*5+om^+1{h zqafFH?O0X{OUO1M^YAPb=F`bd6<0LB=s!LE=ilN39Gach?DYt$CL6UhXTc;$2zpT2dqqQrIZWT*_yH->_|IcgE|Y&S_AJ4lX{3 zlIkT6RWeyS^JtZ1q^3@yK=Cm?J&*-y*C;dpYgTSF&bztX%>V7a(kL+ra#JUT-|=or zs-McUNbE?uO3e#!@v#wf-Fu%ryG^`~69lNs`%MmnTRbrM$471B$+eE{K4hK$mCQ9h-Z$E`tJc<=E)8`p?U8s&`700000NkvXXu0mjfb2aWW literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1d/51248eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1d/51248eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..70fe31aa224ad932de2451d0431a3d53af4ce083 GIT binary patch literal 355 zcmV-p0i6DcP)-rS^s>8d@5ni2hppU0iV;YH8gwNa0%) z{Cz&}Jx|SbT`f+uL?986Pnf0|l@f5k0jz*^zeXXD13Pe$Xi*7R9^s5FmB7$P;6x!% z=kMH0V6IZ20v0@I38qpwTN6bU0_>(U;T<=GYX-1E8)QG}f-;!!681nE=wJ-aU=KPV z^-i_I3K%>@EawIsd5_!T)2R?x1}rE&N|%HcIQa;SqE5+gRv=Fy@M;YVKt`niqbhVk zpSlae%z=$G2Wp@TnqrmWnuKgf72^IDIDhdq{E7X5-;T%%62M`q*b}mOv3|8DyoG;R z;O#l^2#-VHDcnmy=|6xRPAT9SP9@+QP9YE&4z7Z?SGPkvc&h*a002ovPDHLkV1j;z BjTis` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1d/72018cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1d/72018cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..70cb7fc7e0bcfb850d4b365f1bccb5b743913e21 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^96&6^!3HF|1ZAax6icy_X9x!n)NrJ90QsB+9+AZi z4BVX{%xHe{^je@`fTxRNh{nXLlN`Ak40u@7AASF0zb~yy)74d)-}Q|XM+&=H%L1l~ z70X`DZ5Q8J;=>T6aJiv_zhUdQx9rw$B!4Wi^!v;8!uD-LM?h!CZ3$B@rZO?tz^Iy& QK(iS 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/.metadata/.plugins/org.eclipse.core.resources/.history/1e/70f3e032f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/1e/70f3e032f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..13c55f60c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1e/70f3e032f8c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1e/f0398dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1e/f0398dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..17c1fb921f9b7b46aaeefe7afb8302874fb0abd1 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%KAtX)As)xyURua|z<`JK;_Z5y z;?s*`91mY+Vs~LvSAIRQ|I~ek>wo_(4hk(}+Y^;`>!t%UugL`m=C=w5f(6PQ%h%~C hy?JA^CG4Uk|5eN5b2qlEYyz6g;OXk;vd$@?2>`YpFM0p~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/1f/c0845dea21c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1f/c0845dea21c3001119baa706e9d70c26 new file mode 100644 index 000000000..cc2eae5bd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1f/c0845dea21c3001119baa706e9d70c26 @@ -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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.FragmentTransaction; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + mActivity = activity; + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/1f/e1d696ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/1f/e1d696ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6da26f2ae --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/1f/e1d696ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/2/10d077ea0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2/10d077ea0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..8e1efe8c5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2/10d077ea0cc3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/2/20946fb921c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2/20946fb921c3001119baa706e9d70c26 new file mode 100644 index 000000000..489329cd5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2/20946fb921c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2/8099fbcc26c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2/8099fbcc26c3001119baa706e9d70c26 new file mode 100644 index 000000000..85308a097 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2/8099fbcc26c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContent + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/20/02b494ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/20/02b494ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2fd4deea2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/20/02b494ff24c3001119baa706e9d70c26 @@ -0,0 +1,22 @@ + + + + 4 + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/21/30341a1d1dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/21/30341a1d1dc3001119baa706e9d70c26 new file mode 100644 index 000000000..6b6e5c754 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/21/30341a1d1dc3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/22/807e73955bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/22/807e73955bc300111ab8b17b137f3789 new file mode 100644 index 000000000..5770c5688 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/22/807e73955bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindOffset, 0.0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/22/810a91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/22/810a91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a92fb1d4af622cfad770d7c494121719a7896e61 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=d7dtgAr-gYUQ-leFyLX@@b&p` z%gbN)&SLHDYV<0q^J4_6fq?|&@*V6j4#NRakTDF}Z~@#RP$drMna{J{ZM0wU(H|t@ M>FVdQ&MBb@0L8N*<^TWy literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/22/a03a96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/22/a03a96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e284604bb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/22/a03a96ff24c3001119baa706e9d70c26 @@ -0,0 +1,205 @@ +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; + } + + 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); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/22/e3f491ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/22/e3f491ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6f693d631535d4e515227dc08ca341f873ebfdd6 GIT binary patch literal 1007 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU0wmSG7d!(}OiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18J~chQ$R_egL(7_jGX#@i_i=ns2^vxJcXl>hxpZ9^6p0Xj@_! z_~T9h3uB8w6R%S$bC&ss{0H(Eazi;C&F^k-NMaNUid1x1Gr{4JvSUrFLzD*Z!Hu&0 z>2YGA8|PnYez7jpe3YOZ>S)!hKWEzF1XvE#Uk#R=rFeK|w`D z!4JyGPb3oUe@m(!baf=>d{x2sU3v8GX@Z#x=$L7mU z7SCE(kuXgpK=BP{yI}uL&)(QKeT=6RyS+V3H`e&3G-v;Do~C>@&Rn!ArC`Oy*>|7L zcqrJW%d?G+L@?0$MdUtx4zaiwlf@JB6F=XXoP`cb<1e=G@J$cAq9R`3XnGxnR5FzIl;ea~?3f zp7D@>S@^RVGrkypGw6A0ANQe)i*e$^*R^{aJ--Dq%`2Lk{`T_SBU%z^`pHWKz4xT| zaWPKgVclkQPC+uu=80ADT)r^P$(wT0#1H@2u_HpsrY1&4r!=m(edW}x-b_uY4TWkN z1|HKy_!jxi{BHA5^66E*O-t@u_A?g!u#j+CrL!TSYR{2tkD?!Q-}<5wv!|-;9WXzr zmbgZgq$HN4S|t~y0x1R~14Bby14~^)%Me3TD`PV&6AN7fb1MS_MvFb6C>nC}Q!>*k zacd|@WqAqIAPKS|I6tkVJh3R1!7(L2DOJHUH!(dmC^a#qvhZZ84Nwt-r>mdKI;Vst E0C*myI{*Lx literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/23/60ed698bf5c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/23/60ed698bf5c500111689feaa37e8ab14 new file mode 100644 index 000000000..919764a3c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/23/60ed698bf5c500111689feaa37e8ab14 @@ -0,0 +1,10 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public abstract class SlidingActivityBase { + + protected abstract SlidingMenu getSlidingMenu(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/23/b49d8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/23/b49d8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..19532ab10d4fe414d597ed44ed50c91a3e3b9279 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s&XYfl%)5RRG2KmPx>XJ%$TT(5HGK*O1ak257UFsy01aiHFf4G12u u^?&$m-q&fz7T&FR9W0_QnO}Q~fkExE@YIkG=lX%hFnGH9xvX parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/23/f3398dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/23/f3398dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a823841c5e16f4257d18efd0832621a2f3dc355f GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%KAtX)As)xyUQ!e~V8Fq8(N;n1 z^xyoAqP_mw9VZmZ0?ruAPu + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/24/82b789ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/24/82b789ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..b2ce4f0f7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/24/82b789ff24c3001119baa706e9d70c26 @@ -0,0 +1,20 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/24/c0df82c992c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/24/c0df82c992c500111b2a8b7f47e59881 new file mode 100644 index 000000000..21ab9c1e6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/24/c0df82c992c500111b2a8b7f47e59881 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/24/e2a18aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/24/e2a18aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..42528b157a80b0b2932900a07e4904133bf690b4 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SB0XIkLn02py}Xe3KmgB?0DcLn zS%0_hXxhddBJVP_G4soTR+TwiCpJcV&X}3QwWIXzTwhLMHJ=#>pd}2Ru6{1-oD!M parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/25/749089ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/25/749089ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e2078c967 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/25/749089ff24c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/26/519590ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/26/519590ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0bd09806f5c85ad3a33ec80c2a526e9dba34d1f3 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETTu&Frkc@k8uN>rTFyLXm;P>R{ z?#-o|?nQl9Ua&YVWQl+9{Kh9CkJo#*NAA>4+xPwD`<&mEu1}vZI664|W68WNxRjX* q7uY2C$wZnF2qKv(-xu6mlE@I5@4DcHNa}B(#SEUVelF{r5}E+w(lnv~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/26/e048c3922ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/26/e048c3922ac3001119baa706e9d70c26 new file mode 100644 index 000000000..21ab9c1e6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/26/e048c3922ac3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/27/01b494ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/27/01b494ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..88357b0a7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/27/01b494ff24c3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + + + + true + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/27/6033c5f323c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/27/6033c5f323c500111b2a8b7f47e59881 new file mode 100644 index 000000000..b89c1102b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/27/6033c5f323c500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/27/609ea3ecf9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/27/609ea3ecf9c500111689feaa37e8ab14 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/27/609ea3ecf9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/28/31658bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/28/31658bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d8662e3f0fdae62cdee68c184a30fa9e421dc338 GIT binary patch literal 713 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfizez!?|}o;S3Cn7d>4ZLn02pop#z!+EApeUwz>goe2TrwSq2J zirU3kvaXhOUTIG}?do{Paly7dd_m%&JI?q_-onB2%KO8{j^-Q>wzNlYp6R5&dH;Rm z|KbvtPbZZ7*R_9QUBqkhp({MdL+G`PeiKVkcC&4Y!{nAd6Z!S-oqj3U!mzMkIqyf? zf)_G(nEp@p{`aZ-I!9g5h7aq1927O&FPT&GvG@NuQA5$TGve!iOqW^IxiY{>!{pzO z!{3V<)Sk6$zkBfg;!caFvF0E2Z#WAV9{aHQL)vPusEmizHw=GVH2J}B^#kKc_ZNxM zzDF#RGe0;TaIo&I-m~b0*sP8To$2@Yde+QKc8kg_`XHU5q@;HFk@ug+O{X5aZ~nk~ zjknIKwfM~0Z^b864VUMM@zwGAdYt)v<(Nz4IlImB@8#qJ%zn(A@Z29bd}4MpKn$sTM506307QmPCTFYr(@#O zpZ-(V%YE!?30QE(DXivDMdI0PFM+AKOT1>hnX-6tX;O6(d#2d)iSBZ_kN7m7WzTRr zzEA`h)2bz|5hW>!C8<`)MX5lF!N|bSP}jgh*T6i)(9Fuf$jaCl$hI;t2>JhQGm3`X z{FKbJN)!#IR;K1a1kqq?mJtlpAPKS|I6tkVJh3R1!7(L2DOJHUH!(dmC^a#qvhZZ8 Q4Nwt-r>mdKI;Vst0K3d3fB*mh literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/28/70057c8e2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/28/70057c8e2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..b5f078611 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/28/70057c8e2ec3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/28/911396ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/28/911396ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0ea319244 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/28/911396ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/28/b27f91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/28/b27f91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..88726b69160589c8545759440e8d4e69dc984c67 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^azGr$!3HF6SgS1tQk(@Ik;M!Q+?^oIXnykaTA*No zr;B4qM&sKXhJ1$tcw7#es=J@sd2yMiyW@jyg@u( parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/28/f3aa8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/28/f3aa8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..55099d49db309d03035101e55e64396b62af3054 GIT binary patch literal 2875 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 Z0|2By^PX-KG@Sqd002ovPDHLkV1g_UPeK3y literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/29/30090a0115c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/29/30090a0115c3001119baa706e9d70c26 new file mode 100644 index 000000000..249108a1f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/29/30090a0115c3001119baa706e9d70c26 @@ -0,0 +1,1210 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + public 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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(); + } + + public void setContentParent(ViewGroup contentParent) { + mContentParent = contentParent; + } + + @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() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + return generateLayout(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/29/616989ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/29/616989ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..9510eeb98 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/29/616989ff24c3001119baa706e9d70c26 @@ -0,0 +1,21 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/29/905af89f29c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/29/905af89f29c500111b2a8b7f47e59881 new file mode 100644 index 000000000..63d6efa5c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/29/905af89f29c500111b2a8b7f47e59881 @@ -0,0 +1,211 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2a/418c8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2a/418c8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6f747c8f065940a8844587c682fb3c9443ad1ca2 GIT binary patch literal 467 zcmV;^0WAKBP)SO)@i{}u0qYYqHziBfu2L*;{L?D;GxhmUqDjP ziMkTn=nm+BxmDP>FsP2fGnnz3AAnfGAiD%ptMDlguG*u-2|uL;kN%Xenfoz6Wm9neQuJ_f08buH`WL4SA>8mzG9{4uwy+$BT^9a|eO3@D0j4;gS>^u3i8D002ov JPDHLkV1mHE(I@}_ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2a/8022e93b50c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2a/8022e93b50c3001119baa706e9d70c26 new file mode 100644 index 000000000..6f929f1f0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2a/8022e93b50c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2a/a02e166910c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2a/a02e166910c3001119baa706e9d70c26 new file mode 100644 index 000000000..072bdc3bc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2a/a02e166910c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); +// setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); +// setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/107967b493c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/107967b493c500111b2a8b7f47e59881 new file mode 100644 index 000000000..01365babd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/107967b493c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/309ba40953c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/309ba40953c3001119baa706e9d70c26 new file mode 100644 index 000000000..d514364f6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/309ba40953c3001119baa706e9d70c26 @@ -0,0 +1,145 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! +// TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); +// // set the above and behind views if defined in xml +// int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); +// if (viewAbove != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewAbove.setContent(inflater.inflate(viewAbove, this), null); +// } +// int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); +// if (viewBehind != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewBehind.setContent(inflater.inflate(viewBehind, this)); +// } +// float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); +// setBehindOffset((int) offsetBehind); +// float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); +// mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/609e95ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/609e95ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..1bd0eaccb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/609e95ff24c3001119baa706e9d70c26 @@ -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.FragmentTransaction; +import android.view.View; +import android.widget.SpinnerAdapter; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +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); + mNativeTab.setTabListener(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) { + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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 SherlockFragmentActivity) { + mFragmentTransaction = ((SherlockFragmentActivity)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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/2b/80de661d26c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/80de661d26c3001119baa706e9d70c26 new file mode 100644 index 000000000..a52538406 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/80de661d26c3001119baa706e9d70c26 @@ -0,0 +1,771 @@ +package com.actionbarsherlock; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/2b/934f8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/934f8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4215396dd4e51fea9239323d313b72fde0ba86d6 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^%0O(y!3HF+1t+BgDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?E1oWnArY-_Z#r@{8;G<#%>2r*^ujlV;{V25Ur(E)S0c!zKPhEi z+Q+&RrxwTy8fpZ2X-wJl@K&30*P>T$mCG*u%y7IHFk@oZ?G!PI)dwP2k7*f%?N0KT z=P~Pe`QZt37-AUDv?qm~sFi(Y>bsQr3FCw4S+92))lbOG-Y30G>`_~0 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/c04155c62ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/c04155c62ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..88cb84dc5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/c04155c62ac500111b2a8b7f47e59881 @@ -0,0 +1,154 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + /** + * + * @param i The margin on the right of the screen that the behind view scrolls to + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + public void setBehindOffsetResource(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d04376d3f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d04376d3f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..8b3027f3d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d04376d3f8c500111689feaa37e8ab14 @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d08076ac92c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d08076ac92c500111b2a8b7f47e59881 new file mode 100644 index 000000000..ea5892ed2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/d08076ac92c500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2b/e0ba844116c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/e0ba844116c3001119baa706e9d70c26 new file mode 100644 index 000000000..e3736a32d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2b/e0ba844116c3001119baa706e9d70c26 @@ -0,0 +1,1027 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/2d/b2f093ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2d/b2f093ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..502cc16a3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2d/b2f093ff24c3001119baa706e9d70c26 @@ -0,0 +1,33 @@ + + + + + 40dip + + 4dip + + 16dp + + 12dp + + -2dp + + 4dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2e/2054ee332cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2e/2054ee332cc3001119baa706e9d70c26 new file mode 100644 index 000000000..66ac08b69 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2e/2054ee332cc3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2e/c1538aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2e/c1538aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..73050476e77aa798919b829a5566973e231f9d49 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S!aZFaLn02py|Iz^fCC51!MFRR zxpqaJ>-4UOe6iPKwm$=BLD{Wo!i)yScSSDT-Jo*!N?wFe;-MB!VKtu_20%tEPqwzt q4f{lgTEQ5`;-9UxjMeKCf^DQ_uhd?;-Btm#g2B_(&t;ucLK6V6dokDm literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2f/10c93c565bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/10c93c565bc300111ab8b17b137f3789 new file mode 100644 index 000000000..65b92b9ce --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/10c93c565bc300111ab8b17b137f3789 @@ -0,0 +1,136 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/2f/8044d37d16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/8044d37d16c3001119baa706e9d70c26 new file mode 100644 index 000000000..af493d591 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/8044d37d16c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + + if (mDecor == null) { + initActionBar(mDecor); + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/2f/80ef8a9d25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/80ef8a9d25c3001119baa706e9d70c26 new file mode 100644 index 000000000..24679d603 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/2f/80ef8a9d25c3001119baa706e9d70c26 @@ -0,0 +1,214 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3/404300032bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/3/404300032bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..a071b48a7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3/404300032bc500111b2a8b7f47e59881 @@ -0,0 +1,159 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + /** + * + * @param i The margin on the right of the screen that the behind view scrolls to + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param res The dimension resource to be set as the behind offset + */ + public void setBehindOffsetResource(int res) { + int i = (int) getContext().getResources().getDimension(res); + setBehindOffset(i); + } + + /** + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3/43c197ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3/43c197ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..c786dc5c1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3/43c197ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/3/70780f1425c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3/70780f1425c3001119baa706e9d70c26 new file mode 100644 index 000000000..a2202a9fe --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3/70780f1425c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + ((ActionBarSherlockCompat)this.getSherlock()).setContent(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3/70a23da324c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3/70a23da324c3001119baa706e9d70c26 new file mode 100644 index 000000000..963ebaab8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3/70a23da324c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + ((ActionBarSherlockCompat)this.getSherlock()) + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/30/53e897ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/30/53e897ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..a7185d082 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/30/53e897ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/30/f1aa8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/30/f1aa8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6cee9a128d775be645ea2e0acd2817ed87157efc GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nET1Wy;okc@k8Z*AmdP~c!WaR21r z^utc!7dm!6;*{O_$T}$0a;{4DoIM+-U$pe(dJ^jKx&aUP!@cw4)BFVdQ&MBb@0G6aYR{#J2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/31/1068dc514ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/31/1068dc514ec3001119baa706e9d70c26 new file mode 100644 index 000000000..353bf4463 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/31/1068dc514ec3001119baa706e9d70c26 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + this.onCreateOption + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/32/002597ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/002597ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..907a7aa04 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/002597ff24c3001119baa706e9d70c26 @@ -0,0 +1,292 @@ +package com.actionbarsherlock.internal.view.menu; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.ContextMenu.ContextMenuInfo; +import com.actionbarsherlock.internal.view.ActionProviderWrapper; +import com.actionbarsherlock.view.ActionProvider; +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) { + mNativeItem.setActionView(view); + return this; + } + + @Override + public MenuItem setActionView(int resId) { + mNativeItem.setActionView(resId); + return this; + } + + @Override + public View getActionView() { + return mNativeItem.getActionView(); + } + + @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/.metadata/.plugins/org.eclipse.core.resources/.history/32/100aca332bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/100aca332bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..fa7078832 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/100aca332bc500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/32/200295ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/200295ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3dc3fd39e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/200295ff24c3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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 + * @version 4.0.0 + */ +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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/32/72c595ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/72c595ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e41019364 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/72c595ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/32/e07423b75bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/e07423b75bc300111ab8b17b137f3789 new file mode 100644 index 000000000..650c981b2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/e07423b75bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + serAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/32/e16594ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/e16594ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f67853817 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/e16594ff24c3001119baa706e9d70c26 @@ -0,0 +1,38 @@ + + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + 5 + + + 64dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/32/f01b92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/f01b92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d8929fcd1864e92c78f24d34bb07ac0304bf5ebe GIT binary patch literal 395 zcmV;60d)R}P)%)khMb;v@5Yo)-?A$vWI3J{&4Tqm)VM&;#i3-!rXQ;}}A|kSK_xLoQ9!D=| zrQuRX_jo!D&!*woG(4MzXVdU(8lG)+!_Dl;%pOYTRyEwrUVwMtwRCnh!_9059DxJy zTsprAUsT~zdJlX8e>K+(FMd_}2<&RF8#?@^bn(8vHtbfpl-_eLJ!>=!D!!z&OE12( zv`a1CqqIva-mA1rDc-ZR3oqWgvUXO(tc zif5K~i;HKMc8iLSDD9eyk1Fk&iksP%L8V=5@ekmQ^NVfO%k2z5z^Qbob@&(X-FR)u p3HS~A?&0(Ut%!)oJooy?_kZokYAURbJh}h?002ovPDHLkV1n7-uz&yn literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/32/f0fd96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/32/f0fd96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..179b8f037 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/32/f0fd96ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/33/74c595ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/33/74c595ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ed5e79ec6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/33/74c595ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/33/82998eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/33/82998eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ab8ec69844173ccda09e52b81ad27a5df76d4cd6 GIT binary patch literal 572 zcmV-C0>k}@P)jR6%Q#K@^;MZ+DwSq^+h% zP_!xtf_Ukr^ybl{hx{k~3HlSfd-tNJf;W#6l*URbZIYUN$+x@DLlQ_#DhP=KbJ@4d z?3>3vm>B@rlxxLQd;P-m9-THgzpAxGG!1yW5D)4ffO-cU4S%t?r)YdGWOO4jhM%lT z$gSE=x_Gve0j_HeH8J^wOM08!a}xvEw9Ce~Da{Pz+J> + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/35/302995ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/35/302995ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..d0a6d8128 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/35/302995ff24c3001119baa706e9d70c26 @@ -0,0 +1,253 @@ +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 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/.metadata/.plugins/org.eclipse.core.resources/.history/35/31d68dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/35/31d68dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..611d538906ce7aa07ff88cf6cc5ccf78e729fa98 GIT binary patch literal 582 zcmV-M0=fN(P)WG$vw4FcCX~iP#ZL z#Ezgv#79#*s&1dojI+cAPJMQmkZrIiQwNJ5O)mOttk17mc8L&cvoMU!kQ_UoFtLbO zz!d-HXKY4=&$3fUmk1ZWI0ec-zs>!pq|Q@kJSU@WOzCRS5+-37>mm7R8Lg^F?GYkE zBoyQE_yMbobtpr21x*>PeOI?>bqDqY--SH~u7GQNNA@DjpN8vl;D9CDy?cy2$}4=} zU-<6o2fow#3cLa1FfU>%f|NY5;7l!;hc9Mfz6?Kd3>;!21TCTjzVTsyQiuOdGyKLL zkrJWzheFL)VX-6H)nFppRWZTmC)H8V-n8fBiNz#z9k9$5G%LYGc;b_$REAWCR6`m5 z*E%_MJ({2nS8v`qwS3&#TV=rb-Fv5+avqigH< znhH>dnQktv#{&`)VEGWO1G^aub9T=01LcnR UL6aF(f|Me literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/35/51e897ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/35/51e897ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..1c02d4aca --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/35/51e897ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/35/7041672c50c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/35/7041672c50c3001119baa706e9d70c26 new file mode 100644 index 000000000..5e5183d94 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/35/7041672c50c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/35/80e1c04311c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/35/80e1c04311c3001119baa706e9d70c26 new file mode 100644 index 000000000..60bd3d919 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/35/80e1c04311c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); +// setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); +// setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/36/b05c60f4f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/36/b05c60f4f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..a428b1d1b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/36/b05c60f4f9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/36/b0ac19ae25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/36/b0ac19ae25c3001119baa706e9d70c26 new file mode 100644 index 000000000..d912a7d90 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/36/b0ac19ae25c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + ((ActionBarSherlockCompat)this.getSherlock()).setContent(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/36/d1cd91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/36/d1cd91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c843ef3af22f3df1a67ec40f7807c9f76188fd2b GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr?*8<0#p>+uXou@pObhHwBu4M$1`kk47*5n0T@ zz}*SLjOHg#uLTPFdAc};SoFS~;>gutz{8S$^!?BO&wHlFT~V_1=)TZ8!I{mdT_A)Z zztl5%UbEjFE&+!7%~#Kq{9)d)y{;#I@4EEH*bSem)2!T7Pp)1*OL*gdvC7^*b6)~Y OX7F_Nb6Mw<&;$Uil{z^9 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/36/e0fab3fc27c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/36/e0fab3fc27c3001119baa706e9d70c26 new file mode 100644 index 000000000..8382fce39 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/36/e0fab3fc27c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/37/00bd789329c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/37/00bd789329c500111b2a8b7f47e59881 new file mode 100644 index 000000000..54d5a84be --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/37/00bd789329c500111b2a8b7f47e59881 @@ -0,0 +1,210 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/37/210295ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/37/210295ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2497d24ff --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/37/210295ff24c3001119baa706e9d70c26 @@ -0,0 +1,947 @@ +/* + * 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.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 { + /** + * 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); + } + + 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/.metadata/.plugins/org.eclipse.core.resources/.history/37/30f5e4251fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/37/30f5e4251fc3001119baa706e9d70c26 new file mode 100644 index 000000000..d33a38438 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/37/30f5e4251fc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + 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, mDecor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b4cd8144c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b4cd8144c3001119baa706e9d70c26 new file mode 100644 index 000000000..8aa663ba0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b4cd8144c3001119baa706e9d70c26 @@ -0,0 +1,254 @@ +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.ActionBarSherlockCompat; +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; + + public 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 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b7cddb14c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b7cddb14c3001119baa706e9d70c26 new file mode 100644 index 000000000..8cbdf7f46 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/37/c0b7cddb14c3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/39/405b522352c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/39/405b522352c3001119baa706e9d70c26 new file mode 100644 index 000000000..e81e341b9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/39/405b522352c3001119baa706e9d70c26 @@ -0,0 +1,260 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ActionProvider; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.SubMenu; +import android.view.View; + +/** + * A really dumb implementation of the {@link android.view.MenuItem} interface, that's only + * useful for our actionbar-compat purposes. See + * com.android.internal.view.menu.MenuItemImpl in AOSP for a more complete + * implementation. + */ +public class SimpleMenuItem implements MenuItem { + + private SimpleMenu mMenu; + + private final int mId; + private final int mOrder; + private CharSequence mTitle; + private CharSequence mTitleCondensed; + private Drawable mIconDrawable; + private int mIconResId = 0; + private boolean mEnabled = true; + + public SimpleMenuItem(SimpleMenu menu, int id, int order, CharSequence title) { + mMenu = menu; + mId = id; + mOrder = order; + mTitle = title; + } + + public int getItemId() { + return mId; + } + + public int getOrder() { + return mOrder; + } + + public MenuItem setTitle(CharSequence title) { + mTitle = title; + return this; + } + + public MenuItem setTitle(int titleRes) { + return setTitle(mMenu.getContext().getString(titleRes)); + } + + public CharSequence getTitle() { + return mTitle; + } + + public MenuItem setTitleCondensed(CharSequence title) { + mTitleCondensed = title; + return this; + } + + public CharSequence getTitleCondensed() { + return mTitleCondensed != null ? mTitleCondensed : mTitle; + } + + public MenuItem setIcon(Drawable icon) { + mIconResId = 0; + mIconDrawable = icon; + return this; + } + + public MenuItem setIcon(int iconResId) { + mIconDrawable = null; + mIconResId = iconResId; + return this; + } + + public Drawable getIcon() { + if (mIconDrawable != null) { + return mIconDrawable; + } + + if (mIconResId != 0) { + return mMenu.getResources().getDrawable(mIconResId); + } + + return null; + } + + public MenuItem setEnabled(boolean enabled) { + mEnabled = enabled; + return this; + } + + public boolean isEnabled() { + return mEnabled; + } + + // No-op operations. We use no-ops to allow inflation from menu XML. + + public int getGroupId() { + // Noop + return 0; + } + + public View getActionView() { + // Noop + return null; + } + + public MenuItem setActionProvider(ActionProvider actionProvider) { + // Noop + return this; + } + + public ActionProvider getActionProvider() { + // Noop + return null; + } + + public boolean expandActionView() { + // Noop + return false; + } + + public boolean collapseActionView() { + // Noop + return false; + } + + public boolean isActionViewExpanded() { + // Noop + return false; + } + + public MenuItem setOnActionExpandListener(OnActionExpandListener onActionExpandListener) { + // Noop + return this; + } + + public MenuItem setIntent(Intent intent) { + // Noop + return this; + } + + public Intent getIntent() { + // Noop + return null; + } + + public MenuItem setShortcut(char c, char c1) { + // Noop + return this; + } + + public MenuItem setNumericShortcut(char c) { + // Noop + return this; + } + + public char getNumericShortcut() { + // Noop + return 0; + } + + public MenuItem setAlphabeticShortcut(char c) { + // Noop + return this; + } + + public char getAlphabeticShortcut() { + // Noop + return 0; + } + + public MenuItem setCheckable(boolean b) { + // Noop + return this; + } + + public boolean isCheckable() { + // Noop + return false; + } + + public MenuItem setChecked(boolean b) { + // Noop + return this; + } + + public boolean isChecked() { + // Noop + return false; + } + + public MenuItem setVisible(boolean b) { + // Noop + return this; + } + + public boolean isVisible() { + // Noop + return true; + } + + public boolean hasSubMenu() { + // Noop + return false; + } + + public SubMenu getSubMenu() { + // Noop + return null; + } + + public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) { + // Noop + return this; + } + + public ContextMenu.ContextMenuInfo getMenuInfo() { + // Noop + return null; + } + + public void setShowAsAction(int i) { + // Noop + } + + public MenuItem setShowAsActionFlags(int i) { + // Noop + return null; + } + + public MenuItem setActionView(View view) { + // Noop + return this; + } + + public MenuItem setActionView(int i) { + // Noop + return this; + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/39/70c4716c0ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/39/70c4716c0ac3001119baa706e9d70c26 new file mode 100644 index 000000000..5e6e23f01 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/39/70c4716c0ac3001119baa706e9d70c26 @@ -0,0 +1,348 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + 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 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() { + 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/39/a2058aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/39/a2058aff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..b78508478 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/39/a2058aff24c3001119baa706e9d70c26 @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/39/c3358fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/39/c3358fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a2dbf42b74f7fafb6d8a057306a9c021867d035c GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!3HFsSlX9@1d5$JLpXq-h9ji|$mcBZh%9Dc z;O+!rM)Q-W*8&CYJzX3_IA$jQ`2XLYnVI=;y+&GsLz;ns!JqUb2WA}}9-f|K(evAk wfFg6gPD@K@^jg!TZFujONZyK%*Ov1zxbO?iIdA+_5oi>Hr>mdKI;Vst04D7$hX4Qo literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3a/20041b1c53c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/20041b1c53c3001119baa706e9d70c26 new file mode 100644 index 000000000..028e9e9f4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/20041b1c53c3001119baa706e9d70c26 @@ -0,0 +1,5 @@ + + + #999 + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3a/31b892ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/31b892ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..dd69acada --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/31b892ff24c3001119baa706e9d70c26 @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3a/504289ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/504289ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ea7459aaf --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/504289ff24c3001119baa706e9d70c26 @@ -0,0 +1,20 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3a/52b38bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/52b38bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4ea7afa00e2bfe057472ed5a196080fc80ad7383 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr2)kE{-7*QBRJJkl{&7FVVepxUS$Rt1LT2VAvn7lLLt0oo!v4%( tpjG6n=4tr&fORvYRP%q%M>EqU82;Q9of*be(FHVz!PC{xWt~$(699PnDoy|Z literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3a/600f98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/600f98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..81b4cd4d2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/600f98ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/3a/c057f0272ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/c057f0272ec3001119baa706e9d70c26 new file mode 100644 index 000000000..792e9586d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3a/c057f0272ec3001119baa706e9d70c26 @@ -0,0 +1,747 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/3b/c0a56ae184c2001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3b/c0a56ae184c2001119baa706e9d70c26 new file mode 100644 index 000000000..68b7ad492 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3b/c0a56ae184c2001119baa706e9d70c26 @@ -0,0 +1,1917 @@ +/* + * 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.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * Layout manager that allows the user to flip left and right + * through pages of data. You supply an implementation of a + * {@link CustomPagerAdapter} to generate the pages that the view shows. + * + *

Note this class is currently under early design and + * development. The API will likely change in later updates of + * the compatibility library, requiring changes to the source code + * of apps when they are compiled against the newer version.

+ * + *

CustomViewPager is most often used in conjunction with {@link android.app.Fragment}, + * which is a convenient way to supply and manage the lifecycle of each page. + * There are standard adapters implemented for using fragments with the CustomViewPager, + * which cover the most common use cases. These are + * {@link android.support.v4.app.FragmentCustomPagerAdapter}, + * {@link android.support.v4.app.FragmentStateCustomPagerAdapter}, + * {@link android.support.v13.app.FragmentCustomPagerAdapter}, and + * {@link android.support.v13.app.FragmentStateCustomPagerAdapter}; each of these + * classes have simple code showing how to build a full user interface + * with them. + * + *

Here is a more complicated example of CustomViewPager, using it in conjuction + * with {@link android.app.ActionBar} tabs. You can find other examples of using + * CustomViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code. + * + * {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/ActionBarTabsPager.java + * complete} + */ +public class CustomViewAbove extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mWindow; + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private int mFlingDistance; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + + private boolean mLastTouchAllowed = false; + private int mSlidingMenuThreshold = 30; + private CustomViewBehind mCustomViewBehind; + private boolean mEnabled = true; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewAbove#SCROLL_STATE_IDLE + * @see CustomViewAbove#SCROLL_STATE_DRAGGING + * @see CustomViewAbove#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewAbove(Context context) { + super(context); + initCustomViewPager(); + } + + public CustomViewAbove(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewPager(); + } + + void initCustomViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + setAdapter(new CustomPagerAdapter()); + setTransparentWindow(); + + final float density = context.getResources().getDisplayMetrics().density; + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mWindow.position, mWindow.object); + mAdapter.destroyItem(this, mContent.position, mWindow.object); + mAdapter.finishUpdate(this); + mWindow = null; + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mWindow != null && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mWindow.scrolling = true; + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + if (i <= 0) return 0; + return getChildWidth(i-1) + getChildLeft(i-1); + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getCurrentItem() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + if (mCustomViewBehind == null) { + return 0; + } else { + return mCustomViewBehind.getWidth(); + } + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + public boolean isPagingEnabled() { + return mEnabled; + } + + public void setPagingEnabled(boolean b) { + mEnabled = b; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mWindow != null) { + mItems.add(mWindow); + } + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + // TODO + if (mWindow != null) { + + } + if (mContent != null) { + + } + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + private void setTransparentWindow() { + View v = new View(getContext()); + v.setBackgroundColor(android.R.color.transparent); + mAdapter.setBehind(v); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mWindow = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void setContent(View v, ViewGroup.LayoutParams params) { + mAdapter.setContent(v, params); + + ItemInfo ii = new ItemInfo(); + ii.position = 1; + ii.object = mAdapter.instantiateItem(this, 1); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + setCurrentItem(1); + } + + public void setCustomViewBehind(CustomViewBehind cvb) { + mCustomViewBehind = cvb; + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mWindow.object)) { + return mWindow; + } else if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + childLeft = getChildLeft(i); + int childWidth = getChildWidth(i); + child.layout(childLeft, childTop, + childLeft + childWidth, + childTop + child.getMeasuredHeight()); + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. +// if (mDecorChildCount > 0) { +// final int scrollX = getScrollX(); +// int paddingLeft = getPaddingLeft(); +// int paddingRight = getPaddingRight(); +// final int width = getWidth(); +// final int childCount = getChildCount(); +// for (int i = 0; i < childCount; i++) { +// final View child = getChildAt(i); +// final LayoutParams lp = (LayoutParams) child.getLayoutParams(); +// if (!lp.isDecor) continue; +// +// final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; +// int childLeft = 0; +// switch (hgrav) { +// default: +// childLeft = paddingLeft; +// break; +// case Gravity.LEFT: +// childLeft = paddingLeft; +// paddingLeft += child.getWidth(); +// break; +// case Gravity.CENTER_HORIZONTAL: +// childLeft = Math.max((width - child.getMeasuredWidth()) / 2, +// paddingLeft); +// break; +// case Gravity.RIGHT: +// childLeft = width - paddingRight - child.getMeasuredWidth(); +// paddingRight += child.getMeasuredWidth(); +// break; +// } +// childLeft += scrollX; +// +// final int childOffset = childLeft - child.getLeft(); +// if (childOffset != 0) { +// child.offsetLeftAndRight(childOffset); +// } +// } +// } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mWindow != null && mWindow.scrolling) { + needPopulate = true; + mWindow.scrolling = false; + } + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + private boolean thisTouchAllowed(float x) { + if (isMenuOpen()) { + return x >= getBehindWidth() && x <= getWidth(); + } else { + return x >= 0 && x <= mSlidingMenuThreshold; + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + /* + * This method JUST determines whether we want to intercept the motion. + * If we return true, onMotionEvent will be called and we do the actual + * scrolling there. + */ + + if (!mEnabled) { + return false; + } + + if (!thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + // Always take care of the touch gesture being complete. + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + // Release the drag. + if (DEBUG) Log.v(TAG, "Intercept done!"); + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + return false; + } + + // Nothing more to do here if we have decided whether or not we + // are dragging. + if (action != MotionEvent.ACTION_DOWN) { + if (mIsBeingDragged) { + if (DEBUG) Log.v(TAG, "Intercept returning true!"); + return true; + } + if (mIsUnableToDrag) { + if (DEBUG) Log.v(TAG, "Intercept returning false!"); + return false; + } + } + + switch (action) { + case MotionEvent.ACTION_MOVE: { + /* + * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check + * whether the user has moved far enough from his original down touch. + */ + + /* + * Locally do absolute value. mLastMotionY is set to the y value + * of the down event. + */ + final int activePointerId = mActivePointerId; + if (activePointerId == INVALID_POINTER) { + // If we don't have a valid id, the touch down wasn't on content. + break; + } + + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float dx = x - mLastMotionX; + final float xDiff = Math.abs(dx); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (canScroll(this, false, (int) dx, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mInitialMotionX = mLastMotionX = x; + mLastMotionY = y; + return false; + } + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else { + if (yDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + + if (mScrollState == SCROLL_STATE_SETTLING) { + // Let the user 'catch' the pager as it animates. + mIsBeingDragged = true; + mIsUnableToDrag = false; + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(); + mIsBeingDragged = false; + mIsUnableToDrag = false; + } + + if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (!mIsBeingDragged) { + // Track the velocity as long as we aren't dragging. + // Once we start a real drag we will track in onTouchEvent. + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + } + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + + public boolean onTouchEvent(MotionEvent ev) { + if (!mEnabled) { + return false; + } + + if (!mLastTouchAllowed && !thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction(); + + if (action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_POINTER_UP || + action == MotionEvent.ACTION_CANCEL || + action == MotionEvent.ACTION_OUTSIDE) { + mLastTouchAllowed = false; + } else { + mLastTouchAllowed = true; + } + + if (action == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + } + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + // TODO + final float leftBound = 0; + final float rightBound = getBehindWidth(); + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + // scrollX = getChildWidth(mCurItem); + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + pageScrolled((int) scrollX); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int scrollX = getScrollX(); + final int currentPage = scrollX / widthWithMargin; + final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin; + final int activePointerIndex = + MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final int totalDelta = (int) (x - mInitialMotionX); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + return true; + } + + private float mScrollScale; + + public void setScrollScale(float f) { + if (f >= 0 && f <= 1) { + mScrollScale = f; + } + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + if (mCustomViewBehind != null && mEnabled) { + mCustomViewBehind.scrollTo((int)(x*mScrollScale), y); +// mCustomViewBehind.scrollTo(x*mScrollScale, y); + } + } + + private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { + int targetPage; + if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage : currentPage + 1; + } else { + targetPage = (int) (currentPage + pageOffset + 0.5f); + } + return targetPage; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(-1); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (customWidth >= 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3b/f1398dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3b/f1398dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ddfc8e3d5c4131f2460254f183938477fc5a0679 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rhed`}n05R21qr&#kfCPg`@kT=WR_nY-)l@u)2m z9YjR(TNrC5J8zlf@MOx-MX#^q?zd~tP;1Ok`WbQLQ#YGy{=Yfu7pEGW;JmVaai5Cr S@!LSF89ZJ6T-G@yGywoUXh2*5 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3c/322995ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3c/322995ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3247c987c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3c/322995ff24c3001119baa706e9d70c26 @@ -0,0 +1,253 @@ +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 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/.metadata/.plugins/org.eclipse.core.resources/.history/3c/b0dc31fa4fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3c/b0dc31fa4fc3001119baa706e9d70c26 new file mode 100644 index 000000000..93c419c8a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3c/b0dc31fa4fc3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3d/40770b6e0ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3d/40770b6e0ac3001119baa706e9d70c26 new file mode 100644 index 000000000..d01f6c958 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3d/40770b6e0ac3001119baa706e9d70c26 @@ -0,0 +1,349 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); + 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 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() { + 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/3e/006a1cff14c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/006a1cff14c3001119baa706e9d70c26 new file mode 100644 index 000000000..2b66b2702 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/006a1cff14c3001119baa706e9d70c26 @@ -0,0 +1,1210 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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(); + } + + public void setContentParent(ViewGroup contentParent) { + mContentParent = contentParent; + } + + @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() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + return generateLayout(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/3e/1022dd1016c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/1022dd1016c3001119baa706e9d70c26 new file mode 100644 index 000000000..66ab0a610 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/1022dd1016c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public ViewGroup generateLayout(ViewGroup decor) { + 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/3e/500693ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/500693ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..55ab28a24 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/500693ff24c3001119baa706e9d70c26 @@ -0,0 +1,28 @@ + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3e/700c792750c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/700c792750c3001119baa706e9d70c26 new file mode 100644 index 000000000..b163b021e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3e/700c792750c3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3f/20eabc0b93c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/20eabc0b93c500111b2a8b7f47e59881 new file mode 100644 index 000000000..ea5892ed2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/20eabc0b93c500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3f/40f359ee30c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/40f359ee30c500111b2a8b7f47e59881 new file mode 100644 index 000000000..faff8d9f1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/40f359ee30c500111b2a8b7f47e59881 @@ -0,0 +1,41 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceManager mManager; + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context, PreferenceManager manager) { + super(context); + mManager = manager; + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + mPrefs = mManager.createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + CheckBoxPreference cbp = new CheckBoxPreference(getContext()); + cbp.setTitle(title); + cat.addPreference(cbp); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/3f/a0caf7e90cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/a0caf7e90cc3001119baa706e9d70c26 new file mode 100644 index 000000000..f00ba89e5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/a0caf7e90cc3001119baa706e9d70c26 @@ -0,0 +1,1029 @@ +/* + * 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 static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/3f/b0be286bf4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/b0be286bf4c500111689feaa37e8ab14 new file mode 100644 index 000000000..7265b708a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/3f/b0be286bf4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4/503515422ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/4/503515422ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..db7a4e3bc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4/503515422ac500111b2a8b7f47e59881 @@ -0,0 +1,213 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + private SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + public int getBehindOffset() { + return mSlidingMenu.getBehindOffset(); + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + return mSlidingMenu.get + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4/b0eb29d9f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/4/b0eb29d9f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..8a44a0023 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4/b0eb29d9f8c500111689feaa37e8ab14 @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/40/506bf92f31c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/40/506bf92f31c500111b2a8b7f47e59881 new file mode 100644 index 000000000..385b84d6b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/40/506bf92f31c500111b2a8b7f47e59881 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import java.util.prefs.Preferences; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this, new Preferences(this)); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/40/506e84b029c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/40/506e84b029c3001119baa706e9d70c26 new file mode 100644 index 000000000..21ab9c1e6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/40/506e84b029c3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/40/71e390ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/40/71e390ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..517e9f72d0c8d28a22360ad5d73476c25fd4db33 GIT binary patch literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE&~JOTu&Fr5Rcj%_$5Ae=jmr`i z3DvOQxBn=~BCIDR#iS^(^w0Zu6&JUPm!vIx7~`u}yzledo5s8M7#uS86ZssvI8sdD z&xg3?2M7HpA7}46mr}+fqP5gidGgVwQ1_}WN$aob&9(OVStj}6Xj_!ShugM~J~IZM zU$@KD($sJ1b4JGMs?Xp43SH*aH+p$-+40a@k*+<>G~DD-|-{tS&vG^x*%GGq=j0Y+3zJN#Vil?OA~@ zukBM`R53;FYi;h*X6Nv`Uq9z3iuI~5j`7&H`BAcUqjcZh^7x-d8^2$_pe40Fq;EPa z%hqE7x*0h;3a++#0KFc4?e_Zv*^k$mEo1DpzWsL9`(v*67M^+IpR-MVa>nHwC6*2c zw&pTkoOQ_aoMO7bofkh1@}JI}ZKA~9;BBq7`S!))DS4@K0yY}FSDK>kZ?)HK*JGG& z7n!~MQ}4z!!HZux9M^8s)pB{g?A$cwGrvCg`RlIwI(LVEXW4OK`|IMz?e(5Emfz@% z$^^!kYKdz^NlIc#s#S7PDv)9@GB7mMH89sTFbpv?wlXxZGBO2ntqcr|?>AgV(U6;; zl9^VCTZ2=RMLtl2B*=!~{Irtt#G+IN$CUh}R0Yr6#Prml)Wnp^!jq{sKt&9mu6{1- HoD!M parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/41/90537ff530c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/41/90537ff530c500111b2a8b7f47e59881 new file mode 100644 index 000000000..0d407568e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/41/90537ff530c500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/42/34d68dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/42/34d68dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..b2aa9c265b33ecd7504db45721f6277bbc69c44d GIT binary patch literal 438 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah2>S z4={E+nQaFWEGuwK2hw1@3^B*n9tLvudAc};Xq?Zzc+iX4P{i%w`)y*!lC}nMxxP5m z`ipDd|3l#c1q-`17wzs7jap-@cWTC&8}(D4%&X3GaM#!SkY4?Tswdc+PM~^5?gXjDEJr|A(9^w&s1cyzt=Kg=58+)D;SHpB%sRSHFHUToUy>RV`*x3 zp=*`d7Z@F1xvAFw#q#fW_g_%cHx(CZDFFIJwZt`|BqgyV)hf9t6-Y4{85kPs8kp-E z7={=cTNxTy8JPmPRt5&f_Zu#wXvob^$xN%nt--0uA|I$h5@bVgep*R+Vo@rCV@iHf fs)A>3VtQ&&YGO)d;mK4RpdtoOS3j3^P6 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/42/510693ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/42/510693ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..147f36fe8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/42/510693ff24c3001119baa706e9d70c26 @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/42/a3c993ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/42/a3c993ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f9f56045b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/42/a3c993ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/43/106cb88024c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/43/106cb88024c500111b2a8b7f47e59881 new file mode 100644 index 000000000..373779066 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/43/106cb88024c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib.app; + +import SherlockFragmentActivity; + +public class SlidingFragmentActivity extends SherlockFragmentActivity { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/43/222090ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/43/222090ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6ade5eeb37d8388813cee512f8adaad0f6c15397 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETcuyC{kc@k8FE8XhU?9M9Fk3-& z>Hkf73eN%?4n{M7dy#!$d2ZSCCv)eTUt5@6!ODmi{A7$QW>Hb7V|gN6#Q)yLqkTHN Y-hRf#&+ODnfL1Yhy85}Sb4q9e0PNo==Kufz literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/43/706aa73126c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/43/706aa73126c500111b2a8b7f47e59881 new file mode 100644 index 000000000..e69de29bb diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/43/83998eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/43/83998eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ab8ec69844173ccda09e52b81ad27a5df76d4cd6 GIT binary patch literal 572 zcmV-C0>k}@P)jR6%Q#K@^;MZ+DwSq^+h% zP_!xtf_Ukr^ybl{hx{k~3HlSfd-tNJf;W#6l*URbZIYUN$+x@DLlQ_#DhP=KbJ@4d z?3>3vm>B@rlxxLQd;P-m9-THgzpAxGG!1yW5D)4ffO-cU4S%t?r)YdGWOO4jhM%lT z$gSE=x_Gve0j_HeH8J^wOM08!a}xvEw9Ce~Da{Pz+J>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVi#+|ta%!qM2(*u~V)(AB`v%-Gf0&DGr0z}(Q# z($pEI*Cju>G&eP`1g19yq1ObbUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnqfXG!Lpb z1-Dy_aO%|uIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@i-Yj_cI|Bpb0Z$jlkcwMx zuAkO!NfbH$QS$Mn9jBSJr%zE)<@L;o3DWcY$5j1O{ml`tH&g5#IK91!G-tA&$rarkD4;*EzG&-}n5Tb9>HPKCe73%hw)zvd1KRlJZoCOTr%gF&}=` ze5?!8WD96i&q=ub{`>K14s!w<0z;Ho__In{&F9`|Qv3T!!R`as<@>RIR~`JOm`?WC zC(Jp+`!2)wKQ3bDlJyQrERy+~aZIqxhgaG8e04rRZ>XBHL*(o(Ho1wcS`qg2-ZaN0iIdhQeiGhl zaX@9=8@Z#Y75$s!Jibi-KkdNQrIVCzuRYPpGR@R)@2k}HTo-$87JkX>jw!q9;81;c zp_9$QS(6NF?bkdHyHY3L>387B#)!v)pR;TypXf;YJ89|HS62@`+gf+FxrKj`@tGH^ zc#?R2OIfYGWn?_X%5ZgO#_7m{4o;ti5w|}r75*5xxavgb;S+y;#oBJWm(;#Rwom5x zLXGTs9frBtOv@hVmBc@|xbtD)L90mzc$aMzbriifhwJP4g601tmkRy(&RN54z@Yy& VnO{Hc*-23O=IQF^vd$@?2>>?5^-%x- literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/43/d0c39f1928c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/43/d0c39f1928c500111b2a8b7f47e59881 new file mode 100644 index 000000000..1aece2de6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/43/d0c39f1928c500111b2a8b7f47e59881 @@ -0,0 +1,35 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String cat) { + + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/30b3a98848c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/30b3a98848c3001119baa706e9d70c26 new file mode 100644 index 000000000..4c74e6fb5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/30b3a98848c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends Activity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/70ea366f24c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/70ea366f24c500111b2a8b7f47e59881 new file mode 100644 index 000000000..b547a1344 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/70ea366f24c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib.app; + +import SherlockListActivity; + +public class SlidingListActivity extends SherlockListActivity { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/804e638329c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/804e638329c500111b2a8b7f47e59881 new file mode 100644 index 000000000..1a2c948c8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/804e638329c500111b2a8b7f47e59881 @@ -0,0 +1,207 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/80cb36334ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/80cb36334ec3001119baa706e9d70c26 new file mode 100644 index 000000000..26ffcf73c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/80cb36334ec3001119baa706e9d70c26 @@ -0,0 +1,7 @@ + +

+ + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/b0588f1a1fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/b0588f1a1fc3001119baa706e9d70c26 new file mode 100644 index 000000000..3b8dd2374 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/b0588f1a1fc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(decor); + initActionBar(decor); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/44/c06fc2145cc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/c06fc2145cc300111ab8b17b137f3789 new file mode 100644 index 000000000..531ee9c31 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/c06fc2145cc300111ab8b17b137f3789 @@ -0,0 +1,139 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/44/e0a5eacfa4c300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/44/e0a5eacfa4c300111ab8b17b137f3789 new file mode 100644 index 000000000..ad77170b7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/44/e0a5eacfa4c300111ab8b17b137f3789 @@ -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.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/.metadata/.plugins/org.eclipse.core.resources/.history/45/20b4917e27c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/45/20b4917e27c500111b2a8b7f47e59881 new file mode 100644 index 000000000..bbe6559b2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/45/20b4917e27c500111b2a8b7f47e59881 @@ -0,0 +1,19 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + + public MenuScreen(Context context) { + super(context); + Preference p = new Preference(context); + mPrefs = context.getSystemService(Context.); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/45/e0dd634f15c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/45/e0dd634f15c3001119baa706e9d70c26 new file mode 100644 index 000000000..5b822829f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/45/e0dd634f15c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/46/201b429ff3c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/46/201b429ff3c500111689feaa37e8ab14 new file mode 100644 index 000000000..025c29fe0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/46/201b429ff3c500111689feaa37e8ab14 @@ -0,0 +1,1185 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/46/514289ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/46/514289ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0edb33b4b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/46/514289ff24c3001119baa706e9d70c26 @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/46/6020896ef7c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/46/6020896ef7c500111689feaa37e8ab14 new file mode 100644 index 000000000..6c4c00bb4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/46/6020896ef7c500111689feaa37e8ab14 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib.app; + +import com.actionbarsherlock.app.SherlockListActivity; + +public class SlidingListActivity extends SherlockListActivity { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/46/80cdb0cc29c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/46/80cdb0cc29c3001119baa706e9d70c26 new file mode 100644 index 000000000..dc3e30c71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/46/80cdb0cc29c3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/46/a009563952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/46/a009563952c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..949b4aa9ac4ef5f69188b838a106d368727edb13 GIT binary patch literal 1579 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVi;#nHsf*xAj(#L?Bz(AB`v!p+#i#l*G&eP`1g19yuGhr?r(RG}$SnZc?2=lPS(cjOR+OKs0QRy~CKk7t89N!6 zIh$Aj&2z!-7Kq*yoNjS;#pxD(pkwqw5sMVjFd<;-0Wsmp7RZ4o{M0;PYA*sN>zrui zT?`CN^F3W0Ln>|^nI4!T6DZQAewRa0r&Zf`^_o|Ov{q}U#sw)Z+!f`dxzbK|X^TM8^o@V@?-%)|m8F-pTh`1xdCvCv zyz29o#pl16Nb#!szBH{r_dIU7(a-m1)z4|Fr*^(R(4x_izer6g;PG~*b}(_UO<1ESY3)ES+f(`O8N~^}zw9ZJTb~%YE9=-qd_) z-&eW!E?qY&vMe8OwdOrN=V|Sn=h|;vY}0P)F5G?aWdzr$)f>JaP~LWW$~iN`JwBT+ z`kk4f{URqhxnE7S$UE(oN&BP7jjD1VZrh&g>RNy1TIDq5hubcgn&sWzD!)~G-6glZ z&kZUS<%(DBefpFCSl@ + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/47/70e189435dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/47/70e189435dc300111ab8b17b137f3789 new file mode 100644 index 000000000..44131072b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/47/70e189435dc300111ab8b17b137f3789 @@ -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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.FragmentTransaction; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + mActivity = activity; + View blah = activity.getWindow().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) { + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/47/b26196ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/47/b26196ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..b136d50f0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/47/b26196ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/48/44c197ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/48/44c197ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..59d836aec --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/48/44c197ff24c3001119baa706e9d70c26 @@ -0,0 +1,248 @@ +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 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[] LinearLayout = new int[] { + /* 0 */ android.R.attr.divider, + /* 1 */ android.R.attr.showDividers, + /* 2 */ android.R.attr.dividerPadding, + }; + private static final int LinearLayout_divider = 0; + private static final int LinearLayout_showDividers = 1; + private static final int LinearLayout_dividerPadding = 2; + + /** + * 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; + + + public IcsLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.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); + + 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(); + } + + /** + * 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; + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/48/d0174c80f7c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/48/d0174c80f7c500111689feaa37e8ab14 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/48/d0174c80f7c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/00618dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/00618dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ad6e1a4d9f3c81e20676f979a53cea2084ce903d GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%KAtX)As)xyUQ!e~V8Fq8aqs`F z7bNtyi1zwxcbrft3piseKXpIjy5E1@m#%ulQ?d2Tmd%Z9QW*;x*={*DELV8f^e!gW h<;Km*jJ1o5{)rFFF7K literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/304ca72952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/304ca72952c3001119baa706e9d70c26 new file mode 100644 index 000000000..4b3960cf4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/304ca72952c3001119baa706e9d70c26 @@ -0,0 +1,23 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/50e897ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/50e897ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..d13c6cea9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/50e897ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/49/6097013231c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/6097013231c500111b2a8b7f47e59881 new file mode 100644 index 000000000..5635ab150 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/6097013231c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this, new Preference(this)); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/80dcec090bc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/80dcec090bc3001119baa706e9d70c26 new file mode 100644 index 000000000..496f009a3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/80dcec090bc3001119baa706e9d70c26 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/c00e33f230c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/c00e33f230c500111b2a8b7f47e59881 new file mode 100644 index 000000000..6e233a56b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/c00e33f230c500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/49/f0f4be3226c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/49/f0f4be3226c500111b2a8b7f47e59881 new file mode 100644 index 000000000..7218abc73 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/49/f0f4be3226c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib; + +import PreferenceScreen; + +public class MenuScreen extends PreferenceScreen { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4a/60fc8a4d5bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/4a/60fc8a4d5bc300111ab8b17b137f3789 new file mode 100644 index 000000000..32bacca7a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4a/60fc8a4d5bc300111ab8b17b137f3789 @@ -0,0 +1,143 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! +// TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); +// // set the above and behind views if defined in xml +// int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); +// if (viewAbove != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewAbove.setContent(inflater.inflate(viewAbove, this), null); +// } +// int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); +// if (viewBehind != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewBehind.setContent(inflater.inflate(viewBehind, this)); +// } +// float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); +// setBehindOffset((int) offsetBehind); +// float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); +// mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4b/504468fa23c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/504468fa23c500111b2a8b7f47e59881 new file mode 100644 index 000000000..42c983e37 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/504468fa23c500111b2a8b7f47e59881 @@ -0,0 +1,205 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4b/606d4ce884c2001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/606d4ce884c2001119baa706e9d70c26 new file mode 100644 index 000000000..f7873fdc5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/606d4ce884c2001119baa706e9d70c26 @@ -0,0 +1,1516 @@ +/* + * 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.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * Layout manager that allows the user to flip left and right + * through pages of data. You supply an implementation of a + * {@link CustomPagerAdapter} to generate the pages that the view shows. + * + *

Note this class is currently under early design and + * development. The API will likely change in later updates of + * the compatibility library, requiring changes to the source code + * of apps when they are compiled against the newer version.

+ * + *

CustomViewPager is most often used in conjunction with {@link android.app.Fragment}, + * which is a convenient way to supply and manage the lifecycle of each page. + * There are standard adapters implemented for using fragments with the CustomViewPager, + * which cover the most common use cases. These are + * {@link android.support.v4.app.FragmentCustomPagerAdapter}, + * {@link android.support.v4.app.FragmentStateCustomPagerAdapter}, + * {@link android.support.v13.app.FragmentCustomPagerAdapter}, and + * {@link android.support.v13.app.FragmentStateCustomPagerAdapter}; each of these + * classes have simple code showing how to build a full user interface + * with them. + * + *

Here is a more complicated example of CustomViewPager, using it in conjuction + * with {@link android.app.ActionBar} tabs. You can find other examples of using + * CustomViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code. + * + * {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/ActionBarTabsPager.java + * complete} + */ +public class CustomViewBehind extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + private boolean mEnabled = true; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + private int mDecorChildCount; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewBehind#SCROLL_STATE_IDLE + * @see CustomViewBehind#SCROLL_STATE_DRAGGING + * @see CustomViewBehind#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewBehind(Context context) { + super(context); + initCustomViewBehind(); + } + + public CustomViewBehind(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewBehind(); + } + + void initCustomViewBehind() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + setAdapter(new CustomPagerAdapter()); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mContent.position, mContent.object); + mAdapter.finishUpdate(this); + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + return 0; + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getScrollX() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + ViewGroup.LayoutParams params = getLayoutParams(); + return params.width; + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + private ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + public void setContent(View v) { + mAdapter.setBehind(v); + setBackgroundDrawable(v.getBackground()); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + int decorCount = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + if (lp.isDecor) { + decorCount++; + childLeft = getChildLeft(i); + int childWidth = child.getMeasuredWidth(); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } else if ((ii = infoForChild(child)) != null) { + childTop = paddingTop; + if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() + + "x" + child.getMeasuredHeight()); + // TODO PADDING! + childLeft = getChildLeft(i); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mDecorChildCount = decorCount; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. + if (mDecorChildCount > 0) { + final int scrollX = getScrollX(); + int paddingLeft = getPaddingLeft(); + int paddingRight = getPaddingRight(); + final int width = getWidth(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) continue; + + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + int childLeft = 0; + switch (hgrav) { + default: + childLeft = paddingLeft; + break; + case Gravity.LEFT: + childLeft = paddingLeft; + paddingLeft += child.getWidth(); + break; + case Gravity.CENTER_HORIZONTAL: + childLeft = Math.max((width - child.getMeasuredWidth()) / 2, + paddingLeft); + break; + case Gravity.RIGHT: + childLeft = width - paddingRight - child.getMeasuredWidth(); + paddingRight += child.getMeasuredWidth(); + break; + } + childLeft += scrollX; + + final int childOffset = childLeft - child.getLeft(); + if (childOffset != 0) { + child.offsetLeftAndRight(childOffset); + } + } + } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + // we don't want to steal touches from our children + return false; + } + + public boolean onTouchEvent(MotionEvent ev) { + // we don't want to handle touch events here + return false; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(0); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (width != 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4b/a07587ab10c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/a07587ab10c3001119baa706e9d70c26 new file mode 100644 index 000000000..8382fce39 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4b/a07587ab10c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4c/619e95ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/619e95ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2caf5b4a9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/619e95ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/4c/620f98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/620f98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..43281b013 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/620f98ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/4c/70f65436f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/70f65436f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..828de9f28 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4c/70f65436f6c500111689feaa37e8ab14 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4d/12f98fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/12f98fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..16b9bef1267adfd1cbc63961643768b968224dad GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETEKe85kc@k8FK-lVFc4sN6n$}J z)PNZ(|U kO#br3!H&B!tiEU`!|TxaCOKnM0idl6p00i_>zopr0D)>TF#rGn literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4d/201c87f327c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/201c87f327c500111b2a8b7f47e59881 new file mode 100644 index 000000000..101b254fb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/201c87f327c500111b2a8b7f47e59881 @@ -0,0 +1,32 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(context); + mPrefs = p.getPreferenceManager().createPreferenceScreen(context); + } + + public void addCategory(String title) { + + } + + public void addItem(String title, String cat) { + + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4d/34b892ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/34b892ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7168dc77f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/34b892ff24c3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4d/50f3542352c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/50f3542352c3001119baa706e9d70c26 new file mode 100644 index 000000000..dd1a92c37 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4d/50f3542352c3001119baa706e9d70c26 @@ -0,0 +1,203 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import java.util.ArrayList; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +/** + * A really dumb implementation of the {@link android.view.Menu} interface, that's only + * useful for our actionbar-compat purposes. See + * com.android.internal.view.menu.MenuBuilder in AOSP for a more complete + * implementation. + */ +public class SimpleMenu implements Menu { + + private Context mContext; + private Resources mResources; + + private ArrayList mItems; + + public SimpleMenu(Context context) { + mContext = context; + mResources = context.getResources(); + mItems = new ArrayList(); + } + + public Context getContext() { + return mContext; + } + + public Resources getResources() { + return mResources; + } + + public MenuItem add(CharSequence title) { + return addInternal(0, 0, title); + } + + public MenuItem add(int titleRes) { + return addInternal(0, 0, mResources.getString(titleRes)); + } + + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + return addInternal(itemId, order, title); + } + + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return addInternal(itemId, order, mResources.getString(titleRes)); + } + + /** + * Adds an item to the menu. The other add methods funnel to this. + */ + private MenuItem addInternal(int itemId, int order, CharSequence title) { + final SimpleMenuItem item = new SimpleMenuItem(this, itemId, order, title); + mItems.add(findInsertIndex(mItems, order), item); + return item; + } + + private static int findInsertIndex(ArrayList items, int order) { + for (int i = items.size() - 1; i >= 0; i--) { + MenuItem item = items.get(i); + if (item.getOrder() <= order) { + return i + 1; + } + } + + return 0; + } + + public int findItemIndex(int id) { + final int size = size(); + + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return i; + } + } + + return -1; + } + + public void removeItem(int itemId) { + removeItemAtInt(findItemIndex(itemId)); + } + + private void removeItemAtInt(int index) { + if ((index < 0) || (index >= mItems.size())) { + return; + } + mItems.remove(index); + } + + public void clear() { + mItems.clear(); + } + + public MenuItem findItem(int id) { + final int size = size(); + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return item; + } + } + + return null; + } + + public int size() { + return mItems.size(); + } + + public MenuItem getItem(int index) { + return mItems.get(index); + } + + // Unsupported operations. + + public SubMenu addSubMenu(CharSequence charSequence) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public int addIntentOptions(int i, int i1, int i2, ComponentName componentName, + Intent[] intents, Intent intent, int i3, MenuItem[] menuItems) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void removeGroup(int i) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupCheckable(int i, boolean b, boolean b1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupVisible(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupEnabled(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean hasVisibleItems() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void close() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performShortcut(int i, KeyEvent keyEvent, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean isShortcutKey(int i, KeyEvent keyEvent) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performIdentifierAction(int i, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setQwertyMode(boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4e/004e4e77f7c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/004e4e77f7c500111689feaa37e8ab14 new file mode 100644 index 000000000..fd2333019 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/004e4e77f7c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506ad73d16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506ad73d16c3001119baa706e9d70c26 new file mode 100644 index 000000000..65ca66cbf --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506ad73d16c3001119baa706e9d70c26 @@ -0,0 +1,1027 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506d569e5bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506d569e5bc300111ab8b17b137f3789 new file mode 100644 index 000000000..b7a14eb78 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/506d569e5bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindOffset, 0.0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4e/606989ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/606989ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..198384fed --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/606989ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4e/71018cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/71018cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..310c368e7a68479307866c479d1e4eefcf5db311 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^96&6^!3HF|1ZAax6icy_X9x!n)NrJ90QsB+9+AZi z4BVX{%xHe{^je@`h^LEVh{nXLlN`Ak3Qu?vqkba5WyT9CKZ;N%wBhP~?hKK2LK3q{Q@b8ror6q0>Kp=4vJYD@<);T3K0RYm>I5PkM literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/4e/c070ce372ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/c070ce372ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..5c58bdd8f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/4e/c070ce372ac500111b2a8b7f47e59881 @@ -0,0 +1,1873 @@ +package com.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +public class CustomViewAbove extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mWindow; + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private int mFlingDistance; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + + private boolean mLastTouchAllowed = false; + private int mSlidingMenuThreshold = 30; + private CustomViewBehind mCustomViewBehind; + private boolean mEnabled = true; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewAbove#SCROLL_STATE_IDLE + * @see CustomViewAbove#SCROLL_STATE_DRAGGING + * @see CustomViewAbove#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewAbove(Context context) { + super(context); + initCustomViewPager(); + } + + public CustomViewAbove(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewPager(); + } + + void initCustomViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + setAdapter(new CustomPagerAdapter()); + setTransparentWindow(); + + final float density = context.getResources().getDisplayMetrics().density; + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mWindow.position, mWindow.object); + mAdapter.destroyItem(this, mContent.position, mWindow.object); + mAdapter.finishUpdate(this); + mWindow = null; + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mWindow != null && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mWindow.scrolling = true; + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + if (i <= 0) return 0; + return getChildWidth(i-1) + getChildLeft(i-1); + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getCurrentItem() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + if (mCustomViewBehind == null) { + return 0; + } else { + return mCustomViewBehind.getWidth(); + } + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + public boolean isPagingEnabled() { + return mEnabled; + } + + public void setPagingEnabled(boolean b) { + mEnabled = b; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mWindow != null) { + mItems.add(mWindow); + } + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + // TODO + if (mWindow != null) { + + } + if (mContent != null) { + + } + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + private void setTransparentWindow() { + View v = new View(getContext()); + v.setBackgroundColor(android.R.color.transparent); + mAdapter.setBehind(v); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mWindow = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void setContent(View v, ViewGroup.LayoutParams params) { + mAdapter.setContent(v, params); + + ItemInfo ii = new ItemInfo(); + ii.position = 1; + ii.object = mAdapter.instantiateItem(this, 1); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + setCurrentItem(1); + } + + public void setCustomViewBehind(CustomViewBehind cvb) { + mCustomViewBehind = cvb; + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mWindow.object)) { + return mWindow; + } else if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + childLeft = getChildLeft(i); + int childWidth = getChildWidth(i); + child.layout(childLeft, childTop, + childLeft + childWidth, + childTop + child.getMeasuredHeight()); + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. +// if (mDecorChildCount > 0) { +// final int scrollX = getScrollX(); +// int paddingLeft = getPaddingLeft(); +// int paddingRight = getPaddingRight(); +// final int width = getWidth(); +// final int childCount = getChildCount(); +// for (int i = 0; i < childCount; i++) { +// final View child = getChildAt(i); +// final LayoutParams lp = (LayoutParams) child.getLayoutParams(); +// if (!lp.isDecor) continue; +// +// final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; +// int childLeft = 0; +// switch (hgrav) { +// default: +// childLeft = paddingLeft; +// break; +// case Gravity.LEFT: +// childLeft = paddingLeft; +// paddingLeft += child.getWidth(); +// break; +// case Gravity.CENTER_HORIZONTAL: +// childLeft = Math.max((width - child.getMeasuredWidth()) / 2, +// paddingLeft); +// break; +// case Gravity.RIGHT: +// childLeft = width - paddingRight - child.getMeasuredWidth(); +// paddingRight += child.getMeasuredWidth(); +// break; +// } +// childLeft += scrollX; +// +// final int childOffset = childLeft - child.getLeft(); +// if (childOffset != 0) { +// child.offsetLeftAndRight(childOffset); +// } +// } +// } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mWindow != null && mWindow.scrolling) { + needPopulate = true; + mWindow.scrolling = false; + } + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + private boolean thisTouchAllowed(float x) { + if (isMenuOpen()) { + return x >= getBehindWidth() && x <= getWidth(); + } else { + return x >= 0 && x <= mSlidingMenuThreshold; + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + /* + * This method JUST determines whether we want to intercept the motion. + * If we return true, onMotionEvent will be called and we do the actual + * scrolling there. + */ + + if (!mEnabled) { + return false; + } + + if (!thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + // Always take care of the touch gesture being complete. + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + // Release the drag. + if (DEBUG) Log.v(TAG, "Intercept done!"); + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + return false; + } + + // Nothing more to do here if we have decided whether or not we + // are dragging. + if (action != MotionEvent.ACTION_DOWN) { + if (mIsBeingDragged) { + if (DEBUG) Log.v(TAG, "Intercept returning true!"); + return true; + } + if (mIsUnableToDrag) { + if (DEBUG) Log.v(TAG, "Intercept returning false!"); + return false; + } + } + + switch (action) { + case MotionEvent.ACTION_MOVE: { + /* + * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check + * whether the user has moved far enough from his original down touch. + */ + + /* + * Locally do absolute value. mLastMotionY is set to the y value + * of the down event. + */ + final int activePointerId = mActivePointerId; + if (activePointerId == INVALID_POINTER) { + // If we don't have a valid id, the touch down wasn't on content. + break; + } + + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float dx = x - mLastMotionX; + final float xDiff = Math.abs(dx); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (canScroll(this, false, (int) dx, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mInitialMotionX = mLastMotionX = x; + mLastMotionY = y; + return false; + } + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else { + if (yDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + + if (mScrollState == SCROLL_STATE_SETTLING) { + // Let the user 'catch' the pager as it animates. + mIsBeingDragged = true; + mIsUnableToDrag = false; + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(); + mIsBeingDragged = false; + mIsUnableToDrag = false; + } + + if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (!mIsBeingDragged) { + // Track the velocity as long as we aren't dragging. + // Once we start a real drag we will track in onTouchEvent. + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + } + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + + public boolean onTouchEvent(MotionEvent ev) { + if (!mEnabled) { + return false; + } + + if (!mLastTouchAllowed && !thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction(); + + if (action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_POINTER_UP || + action == MotionEvent.ACTION_CANCEL || + action == MotionEvent.ACTION_OUTSIDE) { + mLastTouchAllowed = false; + } else { + mLastTouchAllowed = true; + } + + if (action == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + } + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + // TODO + final float leftBound = 0; + final float rightBound = getBehindWidth(); + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + // scrollX = getChildWidth(mCurItem); + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + pageScrolled((int) scrollX); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int scrollX = getScrollX(); + final int currentPage = scrollX / widthWithMargin; + final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin; + final int activePointerIndex = + MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final int totalDelta = (int) (x - mInitialMotionX); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + return true; + } + + private float mScrollScale; + + public void setScrollScale(float f) { + if (f >= 0 && f <= 1) { + mScrollScale = f; + } + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + if (mCustomViewBehind != null && mEnabled) { + mCustomViewBehind.scrollTo((int)(x*mScrollScale), y); +// mCustomViewBehind.scrollTo(x*mScrollScale, y); + } + } + + private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { + int targetPage; + if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage : currentPage + 1; + } else { + targetPage = (int) (currentPage + pageOffset + 0.5f); + } + return targetPage; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(-1); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (customWidth >= 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5/6058c6e993c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/5/6058c6e993c500111b2a8b7f47e59881 new file mode 100644 index 000000000..5ce8eb543 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5/6058c6e993c500111b2a8b7f47e59881 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5/90b142b93ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5/90b142b93ec3001119baa706e9d70c26 new file mode 100644 index 000000000..0772554cd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5/90b142b93ec3001119baa706e9d70c26 @@ -0,0 +1,21 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/50/329a97ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/50/329a97ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..fbb0ea058 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/50/329a97ff24c3001119baa706e9d70c26 @@ -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; + + 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(); + 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/.metadata/.plugins/org.eclipse.core.resources/.history/50/608eddae95c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/50/608eddae95c500111b2a8b7f47e59881 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/50/608eddae95c500111b2a8b7f47e59881 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/50/90c36dfe4dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/50/90c36dfe4dc3001119baa706e9d70c26 new file mode 100644 index 000000000..09fb3d29c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/50/90c36dfe4dc3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/50/b00e8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/50/b00e8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6536ee63329bb47bec2bf2384aa494923cc2773a GIT binary patch literal 424 zcmV;Z0ayNsP)Km%mHHKmbPH_0G1~QE(|Z z3L*$mIy*=P@!u2&!BHHFf;fuc0uio1*2@YRBct9{0AyU2}iGVkcWw7UUPW(q{Hz&m;6;CQrhm;h30w)z2(`W_Vv zws(S3@Pah`KM=_o2%_3&n+}O86bq(Ag>`_N^4m7drC>+{^&N;72|01L0Qm!AONf3s S@;8qF0000 parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/51/20a7fa5929c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/51/20a7fa5929c3001119baa706e9d70c26 new file mode 100644 index 000000000..21ab9c1e6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/51/20a7fa5929c3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/51/41df92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/51/41df92ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..019d14ef4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/51/41df92ff24c3001119baa706e9d70c26 @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/51/91de89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/51/91de89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e1522ee43 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/51/91de89ff24c3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/51/c0cc6f3315c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/51/c0cc6f3315c3001119baa706e9d70c26 new file mode 100644 index 000000000..8f784cfef --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/51/c0cc6f3315c3001119baa706e9d70c26 @@ -0,0 +1,1170 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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 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() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/52/701959d429c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/52/701959d429c3001119baa706e9d70c26 new file mode 100644 index 000000000..baba995e7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/52/701959d429c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/52/b067091b40c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/52/b067091b40c3001119baa706e9d70c26 new file mode 100644 index 000000000..bcef94480 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/52/b067091b40c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/53/004392ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/53/004392ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d45c7a864d9b36fc5d06ef7650bd22c228e3533e GIT binary patch literal 680 zcmV;Z0$2TsP)JMg@Fn128fNR{httc z2n-9ae~A~-WYQOAyjJ3`v+tFS>H?h>cjZI44!YCDJ4vU-UH-NFC!H?dNqTY9^x~%J z#ZA+To2C~xO)qX5=ft;__PrJUYC9#q>!rbyQFMFHPb=3hoe|&n)9~p|baWUbMthlMtLL6k^E5&wx9H zfkWKo4DxGy27JSv%4KLW#~I|sPnXY+fCHfNj(}ks%-+uyBgtHbMG(R)| O0000 + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/53/73018cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/53/73018cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..1c269205e874bc6addc308efe5be4fb7c5da0edc GIT binary patch literal 917 zcmV;G18V$CDOJO>Ym5d24oA2hD9A9kkZ#C-ocYxQulY$%dG^s1`jD zWrBMf{hI5z?Ps6d&cAMwxpu9tAQSLC;sV+l?CI!atlqGv_K~X}S&7D6#irA$G%zcr zGa^}SvXODrvrsWB#ZkB-c}-Y}>Q0!#L#9IQCX$ZI#7DnF9fJ8(R=8iR{NJvIR3GfdBS0fGXvSYugM@B@Fy~s_l`Jy)|ccqHxmVzApHz{x4N{y z#Xj0V$LH=@zsWY)$4Z)6--edG^VYGh&b$}$F3XeLt5=Uu0`p37@FaypB&t$KuAm9R zq*|yt7WOdr(m%g{dU1bs0-qy(nh~3JDc<<|K^(;cR4G!8UrKd|p;N zi5zZftW#Kk#vM}fdS+hLQ#;Dq?H?_`8P1nhqmR=j>Au${MMR)hh&5HCA z?cjx6pHV1ZFFx`ra1m|YMALE$u3RAxZp(6Eus@DJwzn!G7Cw2Mm%K&AN5Ia`DuuPd r`dvHM#yxB2nYDo;0!e2cs)*3P7gB8$K+RT%00000NkvXXu0mjfr&_ZI literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/53/80ffd98a2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/53/80ffd98a2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..79c1e611f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/53/80ffd98a2ec3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/53/c21794ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/53/c21794ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..502cc16a3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/53/c21794ff24c3001119baa706e9d70c26 @@ -0,0 +1,33 @@ + + + + + 40dip + + 4dip + + 16dp + + 12dp + + -2dp + + 4dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/53/e0a18aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/53/e0a18aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..2d59f354eed3ce3f0564fac30fc8ac278ed4a60f GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%?Vc`-^V;Vpy{TG>rs2jRbt + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/54/83b789ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/54/83b789ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..d7e31b1d1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/54/83b789ff24c3001119baa706e9d70c26 @@ -0,0 +1,20 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/54/e0eb28575dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/54/e0eb28575dc300111ab8b17b137f3789 new file mode 100644 index 000000000..0bdc65c8a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/54/e0eb28575dc300111ab8b17b137f3789 @@ -0,0 +1,205 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/54/f0e8df4316c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/54/f0e8df4316c3001119baa706e9d70c26 new file mode 100644 index 000000000..ac0031ca1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/54/f0e8df4316c3001119baa706e9d70c26 @@ -0,0 +1,1025 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + mActivity = activity; + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/55/54248eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/55/54248eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0279e17a123f8cbb3c7e3a9ce5c5af8e693b6977 GIT binary patch literal 76 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1|-8Yw(bW~!k#XUAsp9}6B-)+^LX%RmN2q0 Ycy4A9FVZ~13zTN?boFyt=akR{01+Y(GXMYp literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/55/725493ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/55/725493ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..bea740178 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/55/725493ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/55/d1eb8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/55/d1eb8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0706c8af658bde9602634950dfe3d5fa5886163f GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%zMd|QAs)xyUfsxfz<`JK;_Z5A z-Y@ApO*&r-OgQM+#9X>wkYiu(tId138dhyGKCm}H$eLN@qysZ=3D*)nlM7YC@0xyy hn}nCMmBhQI$CPR`ipOiMnG7_T!PC{xWt~$(698&aE5rZ* literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/56/907ef79c24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/56/907ef79c24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ec6c86d3e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/56/907ef79c24c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/56/b057160f09c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/56/b057160f09c3001119baa706e9d70c26 new file mode 100644 index 000000000..fbb0ea058 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/56/b057160f09c3001119baa706e9d70c26 @@ -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; + + 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(); + 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/.metadata/.plugins/org.eclipse.core.resources/.history/56/f0f618e311c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/56/f0f618e311c3001119baa706e9d70c26 new file mode 100644 index 000000000..8d4c08d58 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/56/f0f618e311c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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; + + public final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/57/00128e7e24c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/00128e7e24c500111b2a8b7f47e59881 new file mode 100644 index 000000000..e69de29bb diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/57/201b61def9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/201b61def9c500111689feaa37e8ab14 new file mode 100644 index 000000000..bc2da57b8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/57/201b61def9c500111689feaa37e8ab14 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/57/a0c993ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/a0c993ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..625c632ff --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/57/a0c993ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/57/b033f63c27c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/b033f63c27c500111b2a8b7f47e59881 new file mode 100644 index 000000000..6f635c996 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/57/b033f63c27c500111b2a8b7f47e59881 @@ -0,0 +1,17 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + + public MenuScreen(Context context) { + super(context); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/57/c2a691ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/c2a691ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..93066c8403ddaac9b19571152ef499620bcc0e02 GIT binary patch literal 1551 zcmV+q2JrcbP)ZMyJc+a5x+ehm5NR9U3;9%`Hyz-(tJnPJWK72_ZxFO$7HJ!wl=MA(TM` z5z;&LLlB#EA&f^$3`&>pe6X)LdJ&`vfROKm-xd+jMbSqLMZ|438|}{L$EEgM9M^%w zHa{i`W4qmEM~t#0eOdu-0W1NOh@<%YUknyuBI#0I?3#!O*zRI&T@|+kOaOda%IhNv zM;99T5trXGZJ+ZJPec%b)$c$hhFbzf1btKUoQ@WxJHBtqt%Djjh@==IkkXLZmr_R= zETUs(|D2YHL30h7B}jQ1@s(0WN*y++$>%9Px0_7;Q^61da}ymGVa5oGC6I`(Se|An zXj@SBzbdSFK)Um(Fw#d8Mr2~>phE(63xW_TA*G~C`G7107k~`S4FDISDe;mJcscGO zI_^QW2+SjBmZ1U=9v>gytZ(L+77q^(-%!w_2qCD0PZix`L1IaO$h(b>d0@F@G3Eaa zi55W^GL}q#AgNiNjxa=>FZdR(r+ zxE>NCSff^sd0^fBMHn)m#E-cU=7+{dF-K!9f{S1|kOWYSoDj6e26s~&lfViRc^MJj z^>Y9iF9eSfmVwbcxJ7UPa3MH8F;)otZ%)TN7|p{_AvpQV#UO5SLMWM?>!O$+C0vaD z8(N!X1GsBg3ar^sKmkXku0dO*!9}nfXnYiL)Hg=pYKs73(^zvc9aG}t;{#B5>C;Y2 z2$?l`wfXukgc)%>9s%7AsDyH^rRNDOAHyeHMgYzG`@1jfJOi4h!RzZQK)65|cOA0& z28%R3H(uBEzOL&YU%_z=>~=fscDp^gsmfTk*1@j+TejVzGC zpG{n`bp4r^(iKT*Io^&x%OHc_WZd_EkhCG`k)*sFZ|A&V23>!#)HToxrIRJ-1q1Q~ z3qHxB_z~+bgihSWK3otqlC9O%9BoMC(eAot5j0oOB3|pwbjUE4*ONZd@_Kxq z*B8(0XhE_FfV`ZZwcn~gXn8&5;sQ&h03_lPHzc@QD2L`A0DB!p$qE$r97Hn6cmgfM z$;^GEI@&qEx+o;VEJ0ZAK#dKOL6F|xU|IwgE6|`&x_D{{k^myy5)6fQcS{yR>LIlD zb0eL(UISu`k;Dp-=L_3_9uII4xG36?ZZ5uUxd1Up2yq&z=dNHjN&oIh<{D_CLJUbUG4w?002ovPDHLkV1n`$ Bwt@fv literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/57/e018401d24c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/57/e018401d24c500111b2a8b7f47e59881 new file mode 100644 index 000000000..6de5737d9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/57/e018401d24c500111b2a8b7f47e59881 @@ -0,0 +1,36 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/58/30edfe7f0dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/58/30edfe7f0dc3001119baa706e9d70c26 new file mode 100644 index 000000000..b6b2a4a3d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/58/30edfe7f0dc3001119baa706e9d70c26 @@ -0,0 +1,17 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); +// setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); +// setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/58/a2e78eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/58/a2e78eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f74c02b9e18c2faa22585e7bebdcfd0ca74af2e4 GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^59s(?*`6+rAs(G?r#o^TG7xZ`zf?Wo$i2t+|9e$2v=&Zo&G1s6+_&pQ zbIyHljz-QjH&*S{-J;(gu&3N>@$LMyenNedpai4+B)&;SOq0|eu$bkReVyxuhm-Z9>GFCF_99MaBsxVXw=u8GrS3j3^P6 + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/59/a015408c93c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/59/a015408c93c500111b2a8b7f47e59881 new file mode 100644 index 000000000..de8e5a83a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/59/a015408c93c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView, params); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/59/c069972b0dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/59/c069972b0dc3001119baa706e9d70c26 new file mode 100644 index 000000000..5173806a6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/59/c069972b0dc3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/59/d07a8aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/59/d07a8aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6c1415772d03a71c0677f6e2461521bfae829ce9 GIT binary patch literal 2866 zcmV-23(fS2P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z00018Nkl%->o_#B0~lM0RR6305`L6c1|?a Q%K!iX07*qoM6N<$g0$>VYybcN literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5a/509590ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5a/509590ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3e7dcdfdbaf66d51a90633e6f601bfe71b0c5069 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#xSIG!$!Ar_~TGcqy~7@GboNVOeo z`FL%)@k1sD*2PVS;{{wASQ@v8h$x3#@+~m2a+{}M^7C)Is4GMKie-X3Pa7xz&0z3! L^>bP0l+XkKapWP} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5a/91c08eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5a/91c08eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7274274b178bf3689fb0cde6293d716cc19cd277 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol;0U|59*B=E^EX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`73o-U3d5>u0Z{Qqyy%*=eaUL!352pYN+StcB)SJP>#V9b+U;=RED z2qf|=A9d?gTyt;ZSzN%FWhK6zW!r_Lk7KrU{Nfk 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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(); + } + + public void setContentParent(ViewGroup contentParent) { + mContentParent = contentParent; + } + + @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() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + return generateLayout(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/5b/40fd0505fac500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/5b/40fd0505fac500111689feaa37e8ab14 new file mode 100644 index 000000000..d97f6b416 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5b/40fd0505fac500111689feaa37e8ab14 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingListActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5b/b30e8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5b/b30e8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c9972e74bb4fc7416960e238afd47b1ac363e316 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^EI`b~!3HEJ|NhSh5-4`^4B-HR8jh3>AfL0qBeIx* zfx8og8O=|gUJDd7^K@|x;h4Gh+(zC520Y9MizoD2>~^~(JZa^V pUoEkkaeSh9w)TUlKa6vZ+qJ0**((%Vy8umK@O1TaS?83{1OR&wE2RJc literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5c/4018fb3525c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5c/4018fb3525c3001119baa706e9d70c26 new file mode 100644 index 000000000..847d116e4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5c/4018fb3525c3001119baa706e9d70c26 @@ -0,0 +1,1180 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/5c/c0538aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5c/c0538aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..88f11dcb91ee24934f5080dd9611f84d6203cb2b GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S0zF+ELn02py}Xc@!GMSPpu9eJ z%KyNaOMzopr0A6)2vH$=8 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5d/60b6984915c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/60b6984915c3001119baa706e9d70c26 new file mode 100644 index 000000000..d25d000c0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/60b6984915c3001119baa706e9d70c26 @@ -0,0 +1,350 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.ActionBarSherlockCompat; +import com.actionbarsherlock.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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() { + 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/5d/610f98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/610f98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ae7cb1fe0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/610f98ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/5d/815d98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/815d98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..da13bc99f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5d/815d98ff24c3001119baa706e9d70c26 @@ -0,0 +1,818 @@ +/* + * 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) { + dataModel.unregisterObserver(mModelDataSetOberver); + } + 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); + } + } + + /** + * 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()) { + oldDataModel.unregisterObserver(mModelDataSetOberver); + } + 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/.metadata/.plugins/org.eclipse.core.resources/.history/5e/c06fde164dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5e/c06fde164dc3001119baa706e9d70c26 new file mode 100644 index 000000000..a6d408223 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5e/c06fde164dc3001119baa706e9d70c26 @@ -0,0 +1,217 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/5f/f04cf1390ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/5f/f04cf1390ac3001119baa706e9d70c26 new file mode 100644 index 000000000..2cd1019a9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/5f/f04cf1390ac3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); + 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/6/715493ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6/715493ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..a6c6252d2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6/715493ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6/83288cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6/83288cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c8358e9cefce502030416e05dc8faff139b886b2 GIT binary patch literal 2081 zcmV++2;TRJP)YIdx5%v}IY-E={))x>B}kD^;1aO=v<01PBB|;(|LQ1lm?k zLWq;Nn-CY=ae0(~!^>I`t6s zs-B%JpquWw-vVT&b%#DKYKZiAR|9AYVtSC>+D1~E4^t2*_YE}4C7t2scS_b&i9ji7 zBYSvMwdlT0Go+O!I1;=rq$n|BisnJx=53v0;@hqm(7l)*=4rJMo!clNrP~Z@m{E-} z^JZ{ZNHx@{flX?mQSo``X|C|5u79fpM_&?X60Kt|A5rbxJ7+XZpRQ<_6xsZ!_#wo! zj#h1_U5!M-Io2>ob>UEYg+LRijsxnVI$Sub8=TigMynU~iXTIjns`*ZXjCM8l?je< z^3e1OfW}cB&*(9#LY#4(p+|S(CFYo)RH;RK=~N=zD5YZ@e|b@)#etF>)Z-yez@UzD zxn@bF&zGN~8oIPk4dfy-rEX5Ww8$EZ0F70%U;9F1W%-Z($&Ga-Maup1vncKQ7_DKl zn9!@7d$FjFqs1PKM)U|Dr6$Db)oTnV%fNxx{Okxr+DM%Qs^$R=K0p5VBBLXP|Go*uWAqrP!s#9EjG3Y5H)_%&0w$xIP8)2<gS?toB)4w_5VP~5v52jeNf?a@l%z&Ft# z7nB8|dUgD~fFBhAa+9}!Fnz66uJJUZMq$&Z-=x+YQJfJpw%hO;S zbE}u#&MHNeP>Upl#AP)>l0hdeKfNO4(#tQm-Akeu&02@RbFR7XY>6_k1%f(YAT(#fsAW zCKBlg4QBOIpq?mn>zJh1X=9x9hp4F}kQ(@481j?!sz3o)0BA?xOCB;{@vwLHR_qA* zZA`n>5_V~?==zrnj46C`9p$WNjB&zGc+-W7;QUT(*KSn_p>ds2!NyfVppL*7{NFHR zx3J%}=U0sLd(^D`)P?PxcXaJb1;-WXet3d^dmIcA@AOk%p(p(THF8j!=km|#V)bYd zpicX$PljfTc@O)})|@FD=Z~mC2i2imPj;N6y7k2(V~h2N*p=p#-z6}HxcB*hYkSJV z`IFSdb9yY-P}dA6b@>ZL?=z9&3we?^d^OD4aqs1Mx13&f#Qiy{cDn?wohTPSPjL-WpW1m}O&Ju5YPHyotYlm=9`GcY zrwYvY8;-f&ZSM33oCpsge2-Ip%afm3V!sl6q6gM{kN3J3%|Xrhwg)`uVUIiGY!FzE zIO3Qa-0aQX;)a}NjB&uQ|K;9KmvHqg(MeCoc*sw<&DEj$2|GyBp7MmJgBi=!jyvfZ z$6Ymtf^mwAKHp@Hd-~&L-Nsi~>l_hPjymE9wjDU*%(E+7 za!uA`P2O+vKSpg~;?JJlUH||9C3HntbYx+4WjbSWWnpw>05UK!F)c7SEiyAyF*Z6g zGdeOeEigAaFfi_TCsF_a03~!qSaf7zbY(hiZ)9m^c>ppnF)=MLI4v?WR53O>Gc!6e zGc7PTIxsMwC7)_* literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6/c2538aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6/c2538aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..712a551ece87b2544433ac982382a087e7f1731d GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S{5)M8Ln02py}Xf^L4oIp!}}xu zHrx6hVG;aws8xB@i!KMDZA_cCWy>wsRQS4KRST!En$HY_#6vK~{lt8cLjun}a%VT6 c)z9eScC>M27UGHi05qAw)78&qol`;+0QSr+Bme*a literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6/e0bc80581fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6/e0bc80581fc3001119baa706e9d70c26 new file mode 100644 index 000000000..a14a84b04 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6/e0bc80581fc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/60/146a92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/60/146a92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f1eb67323adf05dbd2ed2ac85ca0380cee334d69 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ#0V1dK=^FznmSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn30PZ!4!j+w~@_kK-jY;1gJZ)65y37*PGabQZ{yY%%;i2{aCDiRw# nH#lTg#|ZJc+&C3<00004b3#c}2nYxW zdPRE!~6H3V|7LaeL+kwzxO}{DvWjdA^uWhB*Ox4MVbeVt$Spwgkx< z!VkuXjKgSuY)h6Hw=%|LL;AyKLdLC(F?ASO9Y$7%k=0>jHH%rr7Kwb5&>UvDaCo}j z=j+357qeVAJX{{~a_138(!I8ROa__X7ee%7enXtUzOE0mAw(ah0z?m{B1Ao=21G5U zCPW=Z0YnW(5u`pwA*3EgF{C<11Ed;86J&FYMhHOp8-||_vny?o%`ne52fWVraQiWC zKdv-wupMF9(yd;3%<<_PN8|TOh%C!a80|#$F{54SO;q)d{~Z)(nS?QFWpYf|szS`q zFpt2hCCEz5&mZk`@i_(t4MLWruXxh=CcXUn1{k8P{&E{)e*gdg07*qoM6N<$f@(ay AcmMzZ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/60/b39d8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/60/b39d8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..294991d7931432f4ce0615f83594077185b41e53 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s&X6Hgb%5RRG22KRnVX>4qKXwM^^Uwi5RN9qg%hl7#%FO7Y8A{hJ} m-AWwAG-}%xl(FUbF)^t86Xr1Vx%dsJpTX1B&t;ucLK6TtwI;Oy literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/61/50248eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/61/50248eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6bf21e307ed392bf00fe80b162a6ce9115e62c84 GIT binary patch literal 332 zcmV-S0ki&zP)h$s=>Sb2o({EW84x$2Sq@4Qvb1mj$j~;VIQBr2GX>%-APxay9!he7 z8W7h*gD?q**@0LXh%12j6cFzN;xHg)rA0Yl3bh0|IM)O5QD`2|BGz~0I$#-|1SL$5 zlJGbV2jtPKD8?58g7k0zp)`;V#9XwljI@z*K`Om-0V(CcdbDyt4~XM{*o)XuqGd@4 zDx{8=fp<=lEG6&%R0000 + * 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/.metadata/.plugins/org.eclipse.core.resources/.history/61/70598081f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/61/70598081f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..502e29a1d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/61/70598081f4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); +// getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); +// getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: +// toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/61/71c595ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/61/71c595ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3231080c4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/61/71c595ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/61/913191ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/61/913191ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..528e554abe239137182dd9069d1fa4ba02a109a1 GIT binary patch literal 935 zcmV;Y16cftP)=+L@6RIMT%_@p^A^X5UDRjLANf13Pq%);A`Pd+=!;23pXx; zAif`nPef)@LW&ftmV!!=U?`shr5Kn0)zPywg_Q~)Xf6@UsrA5Be7{a=6EByPs``206cpncnr4<@!q@mA~gUzaA3%HTX+%kDFHYT5Qf!vm`Me|1djAs_x*GR z&!z%kGhWI$<|3X<1;9qUl5@-=4yFR&S{y_@$C%@oE<1op+>aXzjC~!)$_ii$_F+%K z@y9V;#ya3q+!Mu4ce-D|$M^yJarJ;X=I|E&DieT9a7UE58@rw_;mfG%mg3n4+>X7G zDINV8W$>{wd4UPs8tHyn<_K%Vx4t-F{HB0#CbHyT8aIH=*w&T4zhI%?@Yvw4$UHw9 zfiH|AwZ;Wt3m(R<9MXfe~y?7+&yyx)=z7N}~%m5B!YmPaWaH#7@Q+5E; zIqP##(=Vn1;7AlEd2}e2K@tF-TcIq?su`V~Rw@AYX?JP!=ya5wR`qE`V>4fQR+^F$GWKC7sT4IxUFgD9>&BxJs0#D$E0dq8B&$(De03B_O{zBGgT!>|}k{a55 z!O~xj?u?9>EHL(EoJ!?lWDg$AX}pf&%~Sx?@v3~6qvvqAx*Saezy`dwo-+WR!8JMF zpTip|0k{c|kLwhu)oQ!f;y+34?@=W6(zkfKXdO_i)poDN4CtH&58$o=8{em4rdmY+ zbb?>20J>f0o#8w;#fEn(4AdV*y+C*HYaPJI-C#EObp@bT@IwJeLH&YX7XStYpFDt- zf=?R2Fu^AaVA$Z31du2AoO(cqH+@Lz(5e*i5O+3-*HCUO7(002ov JPDHLkV1h8vxv&5L literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/61/e0548665f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/61/e0548665f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/61/e0548665f4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/62/601a552352c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/62/601a552352c3001119baa706e9d70c26 new file mode 100644 index 000000000..91afe11d9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/62/601a552352c3001119baa706e9d70c26 @@ -0,0 +1,304 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.app.Activity; +import android.content.Context; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.view.InflateException; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.slidingmenu.lib.R; + +/** + * A class that implements the action bar pattern for pre-Honeycomb devices. + */ +public class ActionBarHelper { + + private Activity mActivity; + private ViewGroup mActionBar; + private static final String MENU_RES_NAMESPACE = "http://schemas.android.com/apk/res/android"; + private static final String MENU_ATTR_ID = "id"; + private static final String MENU_ATTR_SHOW_AS_ACTION = "showAsAction"; + + protected Set mActionItemIds = new HashSet(); + + public ActionBarHelper(Activity activity, ViewGroup actionbar) { + mActivity = activity; + mActionBar = actionbar; + } + + public ViewGroup getActionBar() { + return mActionBar; + } + + public void onCreate(Bundle savedInstanceState) { + + } + + public void onPostCreate(Bundle savedInstanceState) { +// mActivity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, +// R.layout.actionbar_compat); + setupActionBar(); + + SimpleMenu menu = new SimpleMenu(mActivity); + mActivity.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu); + mActivity.onPrepareOptionsMenu(menu); + for (int i = 0; i < menu.size(); i++) { + MenuItem item = menu.getItem(i); + if (mActionItemIds.contains(item.getItemId())) { + addActionItemCompatFromMenuItem(item); + } + } + } + + /** + * Sets up the compatibility action bar with the given title. + */ + private void setupActionBar() { + final ViewGroup actionBarCompat = getActionBarCompat(); + if (actionBarCompat == null) { + return; + } + + LinearLayout.LayoutParams springLayoutParams = new LinearLayout.LayoutParams( + 0, ViewGroup.LayoutParams.MATCH_PARENT); + springLayoutParams.weight = 1; + + // Add Home button + SimpleMenu tempMenu = new SimpleMenu(mActivity); + SimpleMenuItem homeItem = new SimpleMenuItem( + tempMenu, android.R.id.home, 0, mActivity.getString(R.string.app_name)); + homeItem.setIcon(R.drawable.ic_home); + addActionItemCompatFromMenuItem(homeItem); + + // Add title text + TextView titleText = new TextView(mActivity, null, R.attr.actionbarCompatTitleStyle); + titleText.setLayoutParams(springLayoutParams); + titleText.setText(mActivity.getTitle()); + actionBarCompat.addView(titleText); + } + + /**{@inheritDoc}*/ + public void setRefreshActionItemState(boolean refreshing) { + View refreshButton = mActivity.findViewById(R.id.actionbar_compat_item_refresh); + View refreshIndicator = mActivity.findViewById( + R.id.actionbar_compat_item_refresh_progress); + + if (refreshButton != null) { + refreshButton.setVisibility(refreshing ? View.GONE : View.VISIBLE); + } + if (refreshIndicator != null) { + refreshIndicator.setVisibility(refreshing ? View.VISIBLE : View.GONE); + } + } + + /** + * Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * NOTE: This code will mark on-screen menu items as invisible. + */ + public boolean onCreateOptionsMenu(Menu menu) { + // Hides on-screen action items from the options menu. + for (Integer id : mActionItemIds) { + menu.findItem(id).setVisible(false); + } + return true; + } + + /**{@inheritDoc}*/ + protected void onTitleChanged(CharSequence title, int color) { + TextView titleView = (TextView) mActivity.findViewById(R.id.actionbar_compat_title); + if (titleView != null) { + titleView.setText(title); + } + } + + /** + * Returns a {@link android.view.MenuInflater} that can read action bar metadata on + * pre-Honeycomb devices. + */ + public MenuInflater getMenuInflater(MenuInflater superMenuInflater) { + return new WrappedMenuInflater(mActivity, superMenuInflater); + } + + /** + * Returns the {@link android.view.ViewGroup} for the action bar on phones (compatibility action + * bar). Can return null, and will return null on Honeycomb. + */ + private ViewGroup getActionBarCompat() { + return mActionBar; + } + + /** + * Adds an action button to the compatibility action bar, using menu information from a {@link + * android.view.MenuItem}. If the menu item ID is menu_refresh, the menu item's + * state can be changed to show a loading spinner using + * {@link com.ActionBarHelper.android.actionbarcompat.ActionBarHelperBase#setRefreshActionItemState(boolean)}. + */ + private View addActionItemCompatFromMenuItem(final MenuItem item) { + final int itemId = item.getItemId(); + + final ViewGroup actionBar = getActionBarCompat(); + if (actionBar == null) { + return null; + } + + // Create the button + ImageButton actionButton = new ImageButton(mActivity, null, + itemId == android.R.id.home + ? R.attr.actionbarCompatItemHomeStyle + : R.attr.actionbarCompatItemStyle); + actionButton.setLayoutParams(new ViewGroup.LayoutParams( + (int) mActivity.getResources().getDimension( + itemId == android.R.id.home + ? R.dimen.actionbar_compat_button_home_width + : R.dimen.actionbar_compat_button_width), + ViewGroup.LayoutParams.FILL_PARENT)); + if (itemId == R.id.menu_refresh) { + actionButton.setId(R.id.actionbar_compat_item_refresh); + } + actionButton.setImageDrawable(item.getIcon()); + actionButton.setScaleType(ImageView.ScaleType.CENTER); + actionButton.setContentDescription(item.getTitle()); + actionButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + mActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); + } + }); + + actionBar.addView(actionButton); + + if (item.getItemId() == R.id.menu_refresh) { + // Refresh buttons should be stateful, and allow for indeterminate progress indicators, + // so add those. + ProgressBar indicator = new ProgressBar(mActivity, null, + R.attr.actionbarCompatProgressIndicatorStyle); + + final int buttonWidth = mActivity.getResources().getDimensionPixelSize( + R.dimen.actionbar_compat_button_width); + final int buttonHeight = mActivity.getResources().getDimensionPixelSize( + R.dimen.actionbar_compat_height); + final int progressIndicatorWidth = buttonWidth / 2; + + LinearLayout.LayoutParams indicatorLayoutParams = new LinearLayout.LayoutParams( + progressIndicatorWidth, progressIndicatorWidth); + indicatorLayoutParams.setMargins( + (buttonWidth - progressIndicatorWidth) / 2, + (buttonHeight - progressIndicatorWidth) / 2, + (buttonWidth - progressIndicatorWidth) / 2, + 0); + indicator.setLayoutParams(indicatorLayoutParams); + indicator.setVisibility(View.GONE); + indicator.setId(R.id.actionbar_compat_item_refresh_progress); + actionBar.addView(indicator); + } + + return actionButton; + } + + /** + * A {@link android.view.MenuInflater} that reads action bar metadata. + */ + private class WrappedMenuInflater extends MenuInflater { + MenuInflater mInflater; + + public WrappedMenuInflater(Context context, MenuInflater inflater) { + super(context); + mInflater = inflater; + } + + @Override + public void inflate(int menuRes, Menu menu) { + loadActionBarMetadata(menuRes); + mInflater.inflate(menuRes, menu); + } + + /** + * Loads action bar metadata from a menu resource, storing a list of menu item IDs that + * should be shown on-screen (i.e. those with showAsAction set to always or ifRoom). + * @param menuResId + */ + private void loadActionBarMetadata(int menuResId) { + XmlResourceParser parser = null; + try { + parser = mActivity.getResources().getXml(menuResId); + + int eventType = parser.getEventType(); + int itemId; + int showAsAction; + + boolean eof = false; + while (!eof) { + switch (eventType) { + case XmlPullParser.START_TAG: + if (!parser.getName().equals("item")) { + break; + } + + itemId = parser.getAttributeResourceValue(MENU_RES_NAMESPACE, + MENU_ATTR_ID, 0); + if (itemId == 0) { + break; + } + + showAsAction = parser.getAttributeIntValue(MENU_RES_NAMESPACE, + MENU_ATTR_SHOW_AS_ACTION, -1); + if (showAsAction == MenuItem.SHOW_AS_ACTION_ALWAYS || + showAsAction == MenuItem.SHOW_AS_ACTION_IF_ROOM) { + mActionItemIds.add(itemId); + } + break; + + case XmlPullParser.END_DOCUMENT: + eof = true; + break; + } + + eventType = parser.next(); + } + } 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(); + } + } + } + + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/62/7015e02226c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/62/7015e02226c3001119baa706e9d70c26 new file mode 100644 index 000000000..8e30e37db --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/62/7015e02226c3001119baa706e9d70c26 @@ -0,0 +1,772 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/62/c038db3c52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/62/c038db3c52c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f89c4e96009753edc874c95b947a19d6c4aa4fc0 GIT binary patch literal 2372 zcmaJ@dpwi-A0Jz4b-KBnlXYTd9M|o6Hls~*-DENeMIEu(9_+A-?U9i(-S6n9QvGCg zbR#PFW2vP?9Z8pS4yHmEA*2){ep@H~et(>P&-e8_-|y%9dcWVF>mSeVz<}j*XJcj~ z5Qw=fUq+C2_t3qw47A?@LBbR5W(qUI;9zkyoWzwv2v5E^3c|94+!!bb;_{OdZbQou z2qaDr5(bB{{b@Y0kigYp2y&rB%SIrUxyvP7UK|8tqo5dph>janUBh7od^#?a!Uot9 zZzxvan<9mRQvyPGDRDe1ALs6dT_&e#1%wdH#ma^8A{k9i$9>kNY0tWAA`bf*0>{yD ze+L!D4#awkr4W`v033OMGk|pl2_V_Y#l^(|O9DWE2#|;%$q{s+kx4WFz5;JQs+uS^OizfSS$?@i{q!O7#J&t#j;qj1nV74!LqqL zfkP#<_=HqR%T|*AJ~PZ-3h~?AkxrF~l9HA&)e*x2lrNM!`~9Qny?8$V5|e z6E&lH>4B}A&A83ozv7hBE3dvbATqG<56q_Lh6B98wxLDl=ENfkgB`Az)`pJeWf>dS z>77`W74rxoF_X9j&YUy|K>T$4+^^lU0+G0gP`$qNLd9N1ota+LgjlV|aet#)&I#Sw zm;b$D%C%G)r?{(ruij#8Z2#2u40dY3cZ!ZU6mORMt2Ri z%)R3C%=_7Rf<6v2II1$7h(NfV8S<(HcwXUf#j&0j-=!?BT4y)zl1@kOsKof~7%*^6 zzsT~+MO|>hA6bDoO=R7zxiu z<9tPVdQ*SoDOi8fX=JMdv=`%jCg@O@?8>=qHuietE0ML1;GjBxu)1yh$$65AlGThq zdA@Hy)kwLq=E6i`boqSHdfRCm#r1%LCr$tCrDYxW@INtLO5T0X?p^$ah7@d~U1MKF zu}|a8*x&=Gb0q_0dY$<$DVk$tV>dd(eSkbR6w0 zGI#63ho)D}-Q76WghH#cZh1jhjb0D893G1*fR@C4Vn%#7^z?lcpb-YNfz=w5fL^1H zlsG{1Fj92Ps<*O!ORFs1D4c0~HWbKuyZ_UkG;(}f+<`;g^Ul;iSn_eVW@rkZ?V~{N z0fR%SovmtPYCyxl!3t8n!p`wMeInKV&_dHce8>C4jeyfhqbF0X{T%iq9ugn1!so^F zaitIZ+ssexi%h?lo}swb7*k!^{@ND*K|0TZo6TCM@p+y=`|&7?Wyy01W$U+Ze{K1y z=ROOQ=Co9{sJD=@M*h>&RdbpKoHYaQX07L3yp>-v>&>RMpQf<)fBE5U(!R_WgBIQ% zIUa|@&3O(OO3m+G71y&FjOaWu>M#8D`%Ac0tYgBJImeq}bD8$@?Sgaw)P^4w&PmMz=xR#g$!9+3NOd~5-e-eGTHgqE$=!;JDnliile zg0g+kKXWG9%0Mnbr7*a0!!%o&e6x3K0W#I_fsJQ<)|i)KW$g!RzveX9f_)tM zpznY-Li_Ey+wE0L7@bPc+{l@a!rOM{R3aM^+U$Xk8i%!=waUsJt7~P7Vat57V|~v! zcR1^UZNkNcoV~=M_eX@3mH>M5UQ`R;wt}_NwJx)8@+l`TV~=8bZ8n=i1BhP^(f@Kx SZ2O@5uVFC*7{y+kE&l-&A?fx2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/62/c05b8a4653c3001115d2d454e05194c5 b/.metadata/.plugins/org.eclipse.core.resources/.history/62/c05b8a4653c3001115d2d454e05194c5 new file mode 100644 index 000000000..38145a697 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/62/c05b8a4653c3001115d2d454e05194c5 @@ -0,0 +1,5 @@ + + + #999 + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/63/007dfa8d29c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/63/007dfa8d29c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2cfedf53d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/63/007dfa8d29c500111b2a8b7f47e59881 @@ -0,0 +1,209 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/63/13888dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/63/13888dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c7a9896b0da7b5adcabd4fbcddfd8cfa53627754 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQU;zbjv*T7lQS|h5*V8PD@dJT z6Fe3@|JNavwoMEj44e#^nj)emf)ad+Z6YNPR2Ui9qj$7l4^oi?>SgeB^>bP0l+XkK D`1l&; literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/63/9020d055f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/63/9020d055f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..226b33a8d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/63/9020d055f8c500111689feaa37e8ab14 @@ -0,0 +1,195 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/63/e092273052c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/63/e092273052c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7e52ff595b51cca8586de8eb0835d2f9baa114d3 GIT binary patch literal 2030 zcmaJ?dsGuw9u5ynZ~;S50S!1ASd<8P5E5Wac!Yok4F$qW6lIc3ASKC!WPqqts>CWQ zptW$ckZREb7ORLrqhKqqDu}g3g*_;{JdV4C9z-~@OGPZZ6DziVEIa4S-21!t`@Y}v zoGFfr-Rih<-AV$1;3(QAOu$#BkvYO9F-z~NDXHq z2?#9Tmva~45ePP*GBFiP74Lv#sG1I2Fm!`ji?ay?UYJ1(%d!y+kRq8%4IiAo*#-hi zIUh{nh?!z-B$B1vwqJ)x_Qxj5_GimNL@(1RwU`ps02W19isoW`5Rde?6x7;xvKsx{GT{Yd7+@`fMQ2)4S^|p2{~xMW zzeDS>1myR4|EI7%ai11pBp`Y;S0}?8r|`14(n66s1jbNZB8sY(su-7rVyHd~)dGy;M1N%WL17$d!dl4*vS=3)-^T# z9E@BHuHyKX`GI9#RdWUN-xTl{4o(jr7`b`6$}@EM`LDO8XL;wQPmC|{My?;eaKS4j z^qzgn+3mwFo5~AKEiVHZro|S+E^&LU3B*XRjVlF?9i`?l<0kkxiTXV`uQAkm?LWN7 zJjVj6q1$>5$%RPrBy)+V{R#Vp*sF)6f-tyh1}L3{>h9be>PvdI+Uh}37||=alm^Lc zA)6L&pti$yj8nbi0sW_W@>po~*|_7rX~)_oADE4qE#(ov7@PAN&F}GyDMoJ85FIA{ zX*PUzab3OCDhw>o=vd_oMPBx0jM1o{l{#y)O|HFm#83h0hxN0s*l@+n`qbNe*|(HY zj}4f1>rlp{&mFCwt{jiLdd{naOg<(UAx=&V_y{T2S0AeEGnZxB81h%Q=B@F*Gew?g zKiNyZT~G$hT_p{ZXzbMYE6z-B?sM*difOfyqe<4_o%enBFOs>{ip~^4Q7N&X;2}t% zw9aqa(Q&%O-r<_-D*Gv>w*&oRf@w@~!|#)!Ykwo0X@|KXS{S zOgxgb2CqO7Rq)th(K83w#Z`UZZZ=K5x=#xJ@nBn5^dl4eWizd!p~5(oc+1zmzhQ*B zdl%*M&a^Y?&(Rob9%uNZ)GT?}u9_^6kVo$h_|zvkk-wChb8+wtWu%9>o#GwWiQg`S zok$}49Pm1Qe*M3V?$*4|F12%h0uH$~U6~b&fZCn&u${e;6TeaMar?T3zn4s&DzXh_ z4nZU3wt~O(_7p9Qcxd+wz9d$umAIp04HC95LA`Ue##b-5=}c^wr$svA^faX=&)D-U zUiHCow>|L8<@>)<9XzNLyAxG=_;nC1ogVnrnF9w+%>&ecz?d#HxkNcg^vLbIySZNU zGGkI+pAzq0+&t$39u6UU{4Z6x$Hzw=Bp=TlpV4f$ejV%CUV(tOJbQTS 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/64/904f8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/64/904f8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..eb28ff9a5516c15667fa8fafbc22d608d1f77a06 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^%0O(y!3HF+1t+BgDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?o1QL?ArY-_Z*Jr|WFXM+FkX}IYI~tj_}8!bFJ^a4j((ibs-&WN zGIsXEx)Wtn`lnsEAmpSFI79ccn9RKAsn<`<tk;t}o>yjV{qp%WbL{dki&M)*dw`x~@O1TaS?83{1OTcY Bcf0@q literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/64/e053992f16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/64/e053992f16c3001119baa706e9d70c26 new file mode 100644 index 000000000..eed133d3d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/64/e053992f16c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + + if (mDecor == null) { + initActionBar(mDecor); + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/65/20c526055cc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/65/20c526055cc300111ab8b17b137f3789 new file mode 100644 index 000000000..607ce73e4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/65/20c526055cc300111ab8b17b137f3789 @@ -0,0 +1,139 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml; + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/65/a4058aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/65/a4058aff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..61f76efc6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/65/a4058aff24c3001119baa706e9d70c26 @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/65/d27a8aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/65/d27a8aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..cbbaec588ec98bbc8a518a9ab5a9c469482341ba GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SB0XIkLn02py}Xe3KmgB?fcJu8 z^Zp*+-L#E6MBZg;W9F9wttxZ4PHc?!oG~+pYe(tbxxSpjYCbaz5)ZY&8G8*Bq7ylO npZ&2~Yqrog$!|3Wm+fFU5UE)t_U_Fapd}2Ru6{1-oD!M&D`|W2$+>pS=eAb}M##+^cbdA4dCLPr0$oL~Mm8Bn#4$+9@L$(#*Pp%fW0&@t4F~+Q4$6OeIrG`|nG22@uVa-C zJ=H0n)NABBE9V2ZrDh$}Ob?>#U7^{{%b z^;_|*S@)*|RLscvyw85$_Y2}8p?L-UY)vO;|NFUQJ(sNEA?BESpVrme#d7mboB7l} z-Tl+e|M{(6F|!lpnSU$jtXi?CXvKcs<;$n_y<4FKOaZDTt`Q|Ei6yC4$wjF^iowXh z&`{UFLf61N#L&#jz{twj7|6CVFbMhoZ8M67-29Zxv`Q2WrdForKm^fXYnBlV)F276 tAviy+q&%@GmBBG3KPgqgGdD3kH7GSPrLyp3str&PgQu&X%Q~loCIB{EJ2wCT literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/66/d09cd4b552c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/66/d09cd4b552c3001119baa706e9d70c26 new file mode 100644 index 000000000..32bacca7a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/66/d09cd4b552c3001119baa706e9d70c26 @@ -0,0 +1,143 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! +// TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); +// // set the above and behind views if defined in xml +// int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); +// if (viewAbove != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewAbove.setContent(inflater.inflate(viewAbove, this), null); +// } +// int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); +// if (viewBehind != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewBehind.setContent(inflater.inflate(viewBehind, this)); +// } +// float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); +// setBehindOffset((int) offsetBehind); +// float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); +// mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/67/12888dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/67/12888dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a70b53c59af769e3c98973ad9718670ce27259ff GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQYM}*jv*T7lYjjGZ_h07hy7xL zS%<;BUsuG{45zR mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + cat.addPreference(preference); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/67/70b352830ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/67/70b352830ac3001119baa706e9d70c26 new file mode 100644 index 000000000..03074a1b8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/67/70b352830ac3001119baa706e9d70c26 @@ -0,0 +1,89 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import com.slidingmenu.lib.R; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.ViewGroup; + +/** + * A base activity that defers common functionality across app activities to an {@link + * ActionBarHelper}. + * + * NOTE: dynamically marking menu items as invisible/visible is not currently supported. + * + * NOTE: this may used with the Android Compatibility Package by extending + * android.support.v4.app.FragmentActivity instead of {@link Activity}. + */ +public abstract class ActionBarActivity extends Activity { + + protected ActionBarHelper mActionBarHelper; + + /** + * Returns the {@link ActionBarHelper} for this activity. + */ + protected ActionBarHelper getActionBarHelper() { + return mActionBarHelper; + } + + /**{@inheritDoc}*/ + @Override + public MenuInflater getMenuInflater() { + return mActionBarHelper.getMenuInflater(super.getMenuInflater()); + } + + /**{@inheritDoc}*/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ViewGroup actionbar = (ViewGroup) getLayoutInflater().inflate(R.layout.actionbar_compat, null); + mActionBarHelper = new ActionBarHelper(this, actionbar); + mActionBarHelper.onCreate(savedInstanceState); + } + + /**{@inheritDoc}*/ + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mActionBarHelper.onPostCreate(savedInstanceState); + } + + /** + * Base action bar-aware implementation for + * {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * Note: marking menu items as invisible/visible is not currently supported. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + boolean retValue = false; + retValue |= mActionBarHelper.onCreateOptionsMenu(menu); + retValue |= super.onCreateOptionsMenu(menu); + return retValue; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + mActionBarHelper.onTitleChanged(title, color); + super.onTitleChanged(title, color); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/67/e029c91e24c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/67/e029c91e24c500111b2a8b7f47e59881 new file mode 100644 index 000000000..4cbabaf4e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/67/e029c91e24c500111b2a8b7f47e59881 @@ -0,0 +1,36 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/68/012597ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/68/012597ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..183e87a56 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/68/012597ff24c3001119baa706e9d70c26 @@ -0,0 +1,150 @@ +package com.actionbarsherlock.internal.view.menu; + +import android.content.ComponentName; +import android.content.Intent; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +/** Used to carry an instance of our version of Menu through a native channel. */ +public class MenuMule implements Menu { + private static final String ERROR = "Cannot interact with object designed for temporary " + + "instance passing. Make sure you using both SherlockFragmentActivity and " + + "SherlockFragment."; + + + private final com.actionbarsherlock.view.Menu mMenu; + + public MenuMule(com.actionbarsherlock.view.Menu menu) { + mMenu = menu; + } + + public com.actionbarsherlock.view.Menu unwrap() { + return mMenu; + } + + + @Override + public MenuItem add(CharSequence arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem add(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem add(int arg0, int arg1, int arg2, CharSequence arg3) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem add(int arg0, int arg1, int arg2, int arg3) { + throw new IllegalStateException(ERROR); + } + + @Override + public int addIntentOptions(int arg0, int arg1, int arg2, + ComponentName arg3, Intent[] arg4, Intent arg5, int arg6, + MenuItem[] arg7) { + throw new IllegalStateException(ERROR); + } + + @Override + public SubMenu addSubMenu(CharSequence arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public SubMenu addSubMenu(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public SubMenu addSubMenu(int arg0, int arg1, int arg2, CharSequence arg3) { + throw new IllegalStateException(ERROR); + } + + @Override + public SubMenu addSubMenu(int arg0, int arg1, int arg2, int arg3) { + throw new IllegalStateException(ERROR); + } + + @Override + public void clear() { + throw new IllegalStateException(ERROR); + } + + @Override + public void close() { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem findItem(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem getItem(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean hasVisibleItems() { + return mMenu.hasVisibleItems(); + //throw new IllegalStateException(ERROR); + } + + @Override + public boolean isShortcutKey(int arg0, KeyEvent arg1) { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean performIdentifierAction(int arg0, int arg1) { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean performShortcut(int arg0, KeyEvent arg1, int arg2) { + throw new IllegalStateException(ERROR); + } + + @Override + public void removeGroup(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public void removeItem(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public void setGroupCheckable(int arg0, boolean arg1, boolean arg2) { + throw new IllegalStateException(ERROR); + } + + @Override + public void setGroupEnabled(int arg0, boolean arg1) { + throw new IllegalStateException(ERROR); + } + + @Override + public void setGroupVisible(int arg0, boolean arg1) { + throw new IllegalStateException(ERROR); + } + + @Override + public void setQwertyMode(boolean arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public int size() { + throw new IllegalStateException(ERROR); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/68/924f8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/68/924f8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..b2985860907ac324b509b76731e8ef9e01bcef39 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^%0O(y!3HF+1t+BgDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?E1oWnArY-_Z#r@{8;G<#%>2r*^uo7)-)HXL@_O1Ny%Iq#{YfeF z(mvLmIJH1t&`=}DOJmBWhqv04yB582t6X;JXNKdwfEg3JZl{PztUeIIdQ8h8YDr!LqoiBzejNy&kDcJs%rP689)vmGI{X_;^jtl6gm^<0^v)GdFRa+YOJx z7F>vKtz@b&Rr+MtRJ_Cdn)*bIu9V&{pI@`*?C`z(Yf|Vzp#K;=UHx3vIVCg!08ssU A5dZ)H literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/69/50de51fe25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/69/50de51fe25c3001119baa706e9d70c26 new file mode 100644 index 000000000..13e273f26 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/69/50de51fe25c3001119baa706e9d70c26 @@ -0,0 +1,770 @@ +package com.actionbarsherlock; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; + +import com.actionbarsherlock.app.ActionBar; +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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/69/601e89202cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/69/601e89202cc3001119baa706e9d70c26 new file mode 100644 index 000000000..dc3e30c71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/69/601e89202cc3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/69/90053b045cc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/69/90053b045cc300111ab8b17b137f3789 new file mode 100644 index 000000000..542d791af --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/69/90053b045cc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/69/d13e94ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/69/d13e94ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..35910333b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/69/d13e94ff24c3001119baa706e9d70c26 @@ -0,0 +1,36 @@ + + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + + 64dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/69/e0243f142ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/69/e0243f142ec3001119baa706e9d70c26 new file mode 100644 index 000000000..09b717993 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/69/e0243f142ec3001119baa706e9d70c26 @@ -0,0 +1,1184 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/6a/04618dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/04618dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..60e6c52786e15f108f5b9dc5baf23eee45775415 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%KAtX)As)w*fBgS%&%9ECmdKI;Vst03^XH%m4rY literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6a/10178bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/10178bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..caeff9c33190fc35626822562ed7410b9d7d864e GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{<Lb literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6a/217397ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/217397ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3a4a44675 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/217397ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/6a/739089ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/739089ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2588a492d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6a/739089ff24c3001119baa706e9d70c26 @@ -0,0 +1,18 @@ + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6b/b09d8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6b/b09d8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..673e3bf10d60cc54b6dfef2fcda24575073adf61 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMgJWBc+iXw=G=Ra=)z4*}Q$iB}l;b6k literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6b/e0d18a5724c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6b/e0d18a5724c3001119baa706e9d70c26 new file mode 100644 index 000000000..10bf2fbdc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6b/e0d18a5724c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); +// layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6c/428c8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6c/428c8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..682b2fdec4cdcffe042a0eaba5574fcb553c6fab GIT binary patch literal 505 zcmVavhwv6%LZS|`6cHU3BI+s;(j}rxR}U>ALI;t;n}mlvh$!J-yZtua#I%j$ zOwQ&T8Q}wUMSkBn``+6%%Cao-nJ5SZfglhBcnTy*QWjP42;RUuXn|w-Gn@r3!4%9C z+;SJ#1s`+53r;u-JS+&G)8Q=eVjwW)EYS5?U=Q?t+(O%+X%L*ae6USp(Wf44I z{VTBf*DdH$;99e18zd%PPify*mOc4h3DgW)zaXzPJFd#ED}jzd@IKXer+vefz{o(L zSH{%(p8{RZ0^V<-*kS}|(%8UCAfi$^)3kopWmIldEo%J}dR~)`A1WGIol7IL;ao9F zT=*mq(WtgX@b^ z8v#5LPB(Y&Y|7|Y_!S69s(?1)eUBAs(G?r*GssWFX)$e`(35Y8e@;SI4XCdOETn3puLX+U@Np z`{}{9$F@!!Tb4}GnD8m&^|D{1rP|_tuSV&+Z=MCoD&l+{? zpGeMToA<;$LF?@fW~rUl3#RU765DB+Fm*PQ+)k?pQ&%&Ye!A+gR)$OeeXHaR#_cxq xcQACD7BHRDw&oXmu= 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) { + 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); + } + } + + @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/.metadata/.plugins/org.eclipse.core.resources/.history/6d/d0b95e3e26c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/6d/d0b95e3e26c500111b2a8b7f47e59881 new file mode 100644 index 000000000..9b9dbedac --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6d/d0b95e3e26c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib; + +import android.preference.PreferenceScreen; + +public class MenuScreen extends LinearLayout { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6e/9038117b2ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/6e/9038117b2ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..498740d03 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6e/9038117b2ac500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6e/e0a5563952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6e/e0a5563952c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a85eee381f9cb57790e592ef546908842442749c GIT binary patch literal 1517 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsViy+1SF^#l_Xt*u})q(AB`v%-Gf0&DGr0z}(Q# z($pEI*Cju>G&eP`1g19ysMpZk(#*ud(EzB|6sulPQpha;+U$~Alv$RV;#QQOs{r=0 zRVHq?IOBE;L~jZfw?O^jf>W~)neLk%>?qP^{BrrWpe|jFjohLlAze-@L=LugNf$nJixoMtx86Ob zLocS|3wwrmtCq+gg{E7*9ibsC7mxf3wGW#7y86LRgRFPC#^1ZRWGg(1W?DbDO+Pos zxG+#e^xw0B)lC098J`we_HW&NG_Nq+xImg)Q>&;tEx{ZmG|H zUA}3?xf{z^csiJq)<^WWf7^HXu}`LI4@4@zQ+Nz_mO&g zI0O?`9slrT-;T+f+A3{?qjb7B&u=ff@`|&1-fa(|fJZ+f8Y@4kv#R7arhbJihof8mcanPyq$edOrd z^Ktj1BF`DuZ@ioO%zfeB1+%Lz98Bjwv^Gpf;MNl1vKc=^i&o__hCMvjk@!qZFiHK% zPK)WE-U%9>`X2dy-i2umYQD>!OugoJ>UE`5i1zt@C-#N&x!$(%I^AJ#&)u-@$1c|` zWgX5*;>Y5i!h%i?+H!{6}5aWwowh+QqS5cByU>^W007 zpOrSWgexV}e2nXKB-+$P$f9yT}uu}Pa t+LQjh## literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6f/022597ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/022597ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f030de310 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/022597ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/6f/207397ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/207397ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7d307acb1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/207397ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/6f/300b9f5a2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/300b9f5a2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..dc3e30c71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/300b9f5a2ec3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/6f/30658bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/30658bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0c89f71407e8d51f92ff6a10b1ae40ec902aa04e GIT binary patch literal 546 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877l!}s{b%+Ad7K3vkswhI zFm^kcZ3hx8D{xE)(qO#|6+TOsF)%P{dAc};Se%}E<)W9gqsXz3_j5LNPFu1pO1DK} z+N#=yeg8w_ofMzAMJao1SUGXl-8U7Joy@GYEX@zknfd?wSxaLcYqyHhr&soQ-EO{p zw!~UfNcQJK)l+|B(yvWaZRmKvsC8=g<+E=!6%t;!XnxPxBUZuOVKlwt*0FipR-Y02 zmCh$xWIQ?dubRMH%k4r1TjlOEFztJ(`Lu4f+1J+&0<|T}CPeP?x_?Pcpm5>hNwa5M zzkQR1sjpY$)<2WmGuJ)*zvffcmaNUK`~10Vr~dw8eVc_z%*|+OqxE^sCGQ0OTrOO6 z<>J@Zf0Ym33CMeTp!xW+<7NU=B(%1ExnpuV-^$?oQTEn-hjMN&=46?A$U{|X$JUzr zjr;q)=$3Bvc`c`@@Ze;4?7{TSRWGgUnXHd<-`o)9JVUa&78r!8C9V-ADTyViR>?)F zK#IZ0z|c_Fz+BhBFvQT<%Fw{d$P~!6GB7Z{-*6d4LvDUbW?Cg~4NgrK`9KYlARB`7 r(@M${i&7aJQ}UBi6+Ckj(^G>|6H_V+Po~-c6)||a`njxgN@xNAF&x-_ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/6f/506c78ea0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/506c78ea0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..8e1efe8c5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/506c78ea0cc3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/6f/805d98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/805d98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..379207471 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/805d98ff24c3001119baa706e9d70c26 @@ -0,0 +1,1131 @@ +/* + * 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.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; + +/** + *

+ * 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 SerialExecutor SERIAL_EXECUTOR = new SerialExecutor(); + + private static class SerialExecutor implements Executor { + final LinkedList mTasks = new LinkedList(); + Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + mActive.run(); + } + } + } + + /** + * 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/.metadata/.plugins/org.eclipse.core.resources/.history/6f/9054a9832ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/9054a9832ec3001119baa706e9d70c26 new file mode 100644 index 000000000..5d6e09249 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/6f/9054a9832ec3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/70/044392ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/70/044392ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..03cfb0945d97ecd224763eca5c3136e043c13288 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol;0U|59*B=E^EX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`8Mo-U3d5>t~6?){q5*x2~c-pCBZ5@_=ERFyG literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/71/10e222d4f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/71/10e222d4f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..443abc50d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/71/10e222d4f9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/71/507795ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/71/507795ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..26f0515aa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/71/507795ff24c3001119baa706e9d70c26 @@ -0,0 +1,1191 @@ +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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 (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/.metadata/.plugins/org.eclipse.core.resources/.history/71/d37a8aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/71/d37a8aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..af917e5b6f7de8795ad36c6fe087366dd7806596 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SB0OCjLn02py}Xe3KmgB?fcN%s z6;lG&EqKdxl|3*uLCUs3k#jjy(VH-#G_~1Gd9mf`!G~Hnh1Gm!7$m|O`aCDXBo5UX l|66rxSxar3ZTtpJy}BKi-f!QQ8v*TL@O1TaS?83{1OQ-NFw+14 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/72/30d68dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/72/30d68dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..30cbdc174aab085bf96e59ab39098ec1a0bcbd4c GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%?w&4=As)w*fBgS%&#cG8BEZxy zm1NlC7|c-iVTJ2rvEC??tcxH9FI%^Qs79?$l0=-?MN>nG{Mujhr&UNqv-pZ`Il{xB Xs2c0@Tz2whppguou6{1-oD!M + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/72/60a4603816c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/72/60a4603816c3001119baa706e9d70c26 new file mode 100644 index 000000000..e655ebece --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/72/60a4603816c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + + if (mDecor == null) { + initActionBar(mDecor); + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/72/a0cf768d1cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/72/a0cf768d1cc3001119baa706e9d70c26 new file mode 100644 index 000000000..f2ae2b0d3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/72/a0cf768d1cc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/72/e04c6b0426c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/72/e04c6b0426c3001119baa706e9d70c26 new file mode 100644 index 000000000..8de5450e3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/72/e04c6b0426c3001119baa706e9d70c26 @@ -0,0 +1,770 @@ +package com.actionbarsherlock; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; + +import com.actionbarsherlock.app.ActionBar; +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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/74/00e1273052c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/74/00e1273052c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f6719d228a614e6090fd20281eda453d5002f424 GIT binary patch literal 2349 zcmaJ@cT`hnA5J6;L5d6!88rq(OUZ&jNFa<1kP&1GVo^eJm3)|Caw8!c1WHvsn#P(C z2t?a+6E#4wVwA6jn&KO>Z0?X^Sp(8S!9dJE^$wka(Frxtw9trGXb4iHTH|r2^Hj9J^v7=+? zdG>3(nuPXNH}P#7c=V~>H`V^LUJ93GFihTCAU7&OKPjkQ5y@kCo2A_fEh@*ou6 z1gxFJ0IK^JUkZzahyp=A5si+Ci9yBKqIiN`Xe@z1P-@uNAQcFtFqR84#7M5td`W={ z2$=#lA7t~maHS$6k|zR52t}m-q`={SmE{V*lu1!Aw3xw1V^J7oN=raG{r^KboUdph z7y$em@Bb7Q2F3CLbO0dai3ChV<93=WUGa$&0l)xxf*>Am_fi%8qIe)r7{%kmDS>uy zI)lmPD(%mBI-Tgr6@m;d6Y!*x5DEnpo6RD+k+Bpz0+~#+rQ)zy8ph4umPT=>;q5SZ zES6wLS>jT8Oc4j*f=gW1zg)^Uxyn)C@D-k^fPlRhV7Uu;9QfyyiR^F3LincM7cT4D zvABJci&g}KRyOv(8ohL+m>%W!>)0xcuY(V871J(Ij5R=ftOJ3l7I{+Lg2d0pw|X84 z_ArPO6;w2>i&|kEMr(ksw*bx0C2X8MyGPgG0&&A1)D72K(0HzqxKhJnrFqRtmA*Tf zN!B%ciVniG9cbEniyd^((o6E#`JB@s;UeDiE(C7&7s`|KbB>}WiDk>xXMPLEo~>Lw z2wkBfmP3zfh$^e9>Moiv|MM*DK5y=f_FIdw*N=xDWCX~KCAB=M{Ap)r;48Ip%U4aG zI7tq;Yll2`#CqVd^8k!#v$|Go{NbC?wuJ!9Mw9LYn`(0C|J7DoY)+IzBiwrO}<>1PyncBFQ|4 zQjf3q+7Iik+o+Qer^72zX~)hqYvNe^$)j5uLhJ z8NhNJG}59D$(K#2&bMB_W@MX%kN7E?sWZ`;X_aPOY8nH~%aPWzDmteoJ7P_}3BL7l z>Jm$0A~w2GY;a0ej*s~0-2b)(<-+`Z*X$(rsdW{3KGVd(<2c$4`+Lv!%##CeUqUZe z7%S_E(aQ3zkE;98`Qi0L@H#OZPkV777zv&*8W+E#%*X^e=p@t z;>FAvj@JXV2k9afjfgpYc6054X6^p|V?)^{2PdnZk6j;GJo`uw_<2f&cBR9}Q7zZ$ zp=n^>!(#Pc`)hVU5425{MBOc>mf|3&ZoeALGs59^rnwWmkU;6?rJ9W1|A`S{1w_KS4>#d^GHBD+#@>1^^ zuaSLpI689XNp+$;q=)94=eMODQ@&vExQqts1w0>06r?|fKO=a%-21d5kcT+L>wl_6j8z1&6N(yte(zc#P$`)_*N(|%? zJ|=E&%0O&z-v&lAszb2sIB(ssw|n)$Lv}3X=VrOychNpNzx-IU!jw?F&mH&~{Ep&}Cr}GX&9VlnxN@MBy4(Ein zjZ-Yv52D`hW#+KzEUcew+gR!LPpU*$c=GJ5;U>kM5(_D6Jnee68Dm`wiLNZWY(D75 zoeb`Csz$44o;YHrndG0Gek*dE*<=sjrgd9O6$*mj!2P0@^~uqem-i>Mu4Qsda*|ue zvMJKUQEpD_nv@a9$}K0Rx$xwU1jClX+gGmIqiI1#S9)H)NVUnrMYP(v7~X5D$(K7> zM;Y>>5CuDqHCW(!3Lj+I?5sTjlWa2^>w@a!Pxgs!(7m55ORNepi+{Zw(>}4 + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/74/a08e698a27c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/74/a08e698a27c3001119baa706e9d70c26 new file mode 100644 index 000000000..b8470e14e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/74/a08e698a27c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/75/002e00504ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/75/002e00504ec3001119baa706e9d70c26 new file mode 100644 index 000000000..691fe0c07 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/75/002e00504ec3001119baa706e9d70c26 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + this.onCreateOption + } + + @Override + public boolean onCreateOptionsMenu(MenuInflater inflater) { + + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/75/a0768cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/75/a0768cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a280eabf59b5eb69fa2a84280402b63d5e1bb8f0 GIT binary patch literal 524 zcmeAS@N?(olHy`uVBq!ia0vp^%0O(y!3HF+1t+BgDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9q_DjO#pI977^n-`=$MKI|ZI{A2#4tV=npb9cQAXy4X!_bwM}{Q4K( z1sl8bnxc=22fURRmTQmkS`l-5N%{4LzmAq3{WkJ?oSyR(lyW*m>cW(jDj1r7drC_% z+Ahf4U7%?EfVHA#U$%eE)HUhV{* zGqMRv58QeS1t+_UJh{!Nwtjop`q`x&KXzE!mvvsrOU)9V|3+xFYu0w7ttSN+pN66C zV4oMA@AG&3wK%+`$wcPZ<#Ux2T-c9-*heq_yZUm|{V%D1UlxhJm0zYfUETgVr;hpA zt-Fj|Jsx=O$lYh^6WL+vBibSA6WURD#!g`Ij9SHG25Jg!2FnzxlYN}N9h%V=a_mM! z$e|leQ;yweap>IrEpmd};fhV2Zrn5uN|m^)*v*dyQIi{G2ej@g`j zy#1roz10ezmNeBYwbLI^0W9{MT&2dcxOa)`zb@?O?Gu2 z*S413TzCHUdV}>`f)DaiKP_4HkL&Y-WAl>F%y}d1AGY65et#XKh5dqWo7Y|}14bu< Mr>mdKI;Vst0N8Ej(f|Me literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/75/e0e81e9144c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/75/e0e81e9144c3001119baa706e9d70c26 new file mode 100644 index 000000000..4cb713cbe --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/75/e0e81e9144c3001119baa706e9d70c26 @@ -0,0 +1,217 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/11178bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/11178bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..1d836f65a1fffea301e9cf36770b21b48b3b8132 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SVmw_OLn02py|R(B!9jra;>r_8 z?%b*io|Yn;UGT9};ZTu}!9}%xc^%IgtXD4oJ@0X-F7B%4f|j+c$=0hv54CU#tNF|@ sNQ5wMgi8eI0r?xYZ}@0_Yf6jsMX$B_pXOhT0oudh>FVdQ&MBb@0DzD;x&QzG literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/20560baaf3c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/20560baaf3c500111689feaa37e8ab14 new file mode 100644 index 000000000..832597e04 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/76/20560baaf3c500111689feaa37e8ab14 @@ -0,0 +1,1185 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/76/702831bf52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/702831bf52c3001119baa706e9d70c26 new file mode 100644 index 000000000..8f733bc81 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/76/702831bf52c3001119baa706e9d70c26 @@ -0,0 +1,145 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/82288cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/82288cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..40d0d1645cbf05e30bf092ace45403281da7f318 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^96&6^!3HF|1ZAax6icy_X9x!n)NrJ90QsB+9+AZi z4BVX{%xHe{^je@`oTrOph{nXLlMZq=7znVWA2oV&$ZSjW?F|h7ziq5jS#e}ezd(V) z{M(JTeF@SBrcbxn{QE=WZYK^04VRD=846z*9&b9ovtVvpnl(eT%D#{N!SzC3^S3#* f<|u1MCr7h0-;i__`(soEw28sf)z4*}Q$iB}%FaDT literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/a1058aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/a1058aff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..4af5e22a9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/76/a1058aff24c3001119baa706e9d70c26 @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/c0ea58865bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/c0ea58865bc300111ab8b17b137f3789 new file mode 100644 index 000000000..55aca3155 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/76/c0ea58865bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindOffset, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/76/e1838fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/76/e1838fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7e6c047d665106798c706744dee042931d0dbc77 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nET6i*k&kc@k8FCXMQ;K0G+aC$T2 zZ~dcBCT%GY=oc*8Z`5@0?ndkHd$txIUv=iq$x1%fPwpO}U!OGK0du$`OSx1W{%~-d g&^ht_>ttc^?peW`&R>iA3bc>G)78&qol`;+04`QPF8}}l literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/77/719089ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/77/719089ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..d470e9859 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/77/719089ff24c3001119baa706e9d70c26 @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/78/1098152e2cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/78/1098152e2cc3001119baa706e9d70c26 new file mode 100644 index 000000000..86ede6fee --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/78/1098152e2cc3001119baa706e9d70c26 @@ -0,0 +1,1183 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/78/a0a5d5fb94c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/78/a0a5d5fb94c500111b2a8b7f47e59881 new file mode 100644 index 000000000..c6e8b6624 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/78/a0a5d5fb94c500111b2a8b7f47e59881 @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/78/b16196ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/78/b16196ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..a670b1f64 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/78/b16196ff24c3001119baa706e9d70c26 @@ -0,0 +1,65 @@ +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) { + super(context); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineLinearLayout(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); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/78/f0c6d0d2f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/78/f0c6d0d2f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..f06828166 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/78/f0c6d0d2f6c500111689feaa37e8ab14 @@ -0,0 +1,200 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.AdapterView.OnItemClickListener; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; +import com.slidingmenu.lib.app.SlidingActivity.MenuListItem; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuList; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuListAdapter; + +public class SlidingFragmentActivity extends SherlockFragmentActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = LayoutInflater.from(SlidingFragmentActivity.this). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/79/9058251f40c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/79/9058251f40c3001119baa706e9d70c26 new file mode 100644 index 000000000..7ac7e0b90 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/79/9058251f40c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + View v = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7a/40df92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7a/40df92ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..875ec3e1b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7a/40df92ff24c3001119baa706e9d70c26 @@ -0,0 +1,31 @@ + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7a/70728eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7a/70728eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..92da2f0dd3711a2ceb843768cafd6b91a2807b43 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^{6MVD!3HFkzrK_Oq*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMg#;uvX%d>fBtxy+SfFGJhTv9Z9>9n%%Tr7{oI+Q@DMao9hQt@O?p#8;eZd15IY| MboFyt=akR{068-?^#A|> literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/219192ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/219192ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f46f7a044 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/219192ff24c3001119baa706e9d70c26 @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/308b22fbf5c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/308b22fbf5c500111689feaa37e8ab14 new file mode 100644 index 000000000..2b0e6a13d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/308b22fbf5c500111689feaa37e8ab14 @@ -0,0 +1,12 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + protected SlidingMenu getSlidingMenu(); + + protected boolean isStatic(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/32d68dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/32d68dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..cf2f01b1f456820ba041c0a9d1ef3a80ccf0e6c3 GIT binary patch literal 622 zcmV-!0+IcRP)Ly$}0$;qwZgs8gxBCE_n{3+(XS)eXMe`V{u9>$(f`y2WB4h!PgqLMpBaZVAZK zAZ1SgiHPAZQxkWTjWKBoiV-PC?_V6u=(8b7YMN#^5n%%1DYYM1G&i7_kTUo}oNX-) zrxO8C*EN8>GMo}V-xfT1SM|u4P?3~3T3;(<>2drW&+06RKc*K`7xcRZO#lD@07*qo IM6N<$f(6SHK>z>% literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/4016ef4f2bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/4016ef4f2bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..e17769367 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/4016ef4f2bc500111b2a8b7f47e59881 @@ -0,0 +1,1877 @@ +package com.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +public class CustomViewAbove extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mWindow; + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private int mFlingDistance; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + + private boolean mLastTouchAllowed = false; + private int mSlidingMenuThreshold = 30; + private CustomViewBehind mCustomViewBehind; + private boolean mEnabled = true; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewAbove#SCROLL_STATE_IDLE + * @see CustomViewAbove#SCROLL_STATE_DRAGGING + * @see CustomViewAbove#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewAbove(Context context) { + super(context); + initCustomViewPager(); + } + + public CustomViewAbove(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewPager(); + } + + void initCustomViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + setAdapter(new CustomPagerAdapter()); + setTransparentWindow(); + + final float density = context.getResources().getDisplayMetrics().density; + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mWindow.position, mWindow.object); + mAdapter.destroyItem(this, mContent.position, mWindow.object); + mAdapter.finishUpdate(this); + mWindow = null; + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mWindow != null && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mWindow.scrolling = true; + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + if (i <= 0) return 0; + return getChildWidth(i-1) + getChildLeft(i-1); + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getCurrentItem() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + if (mCustomViewBehind == null) { + return 0; + } else { + return mCustomViewBehind.getWidth(); + } + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + public boolean isPagingEnabled() { + return mEnabled; + } + + public void setPagingEnabled(boolean b) { + mEnabled = b; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mWindow != null) { + mItems.add(mWindow); + } + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + // TODO + if (mWindow != null) { + + } + if (mContent != null) { + + } + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + private void setTransparentWindow() { + View v = new View(getContext()); + v.setBackgroundColor(android.R.color.transparent); + mAdapter.setBehind(v); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mWindow = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void setContent(View v, ViewGroup.LayoutParams params) { + mAdapter.setContent(v, params); + + ItemInfo ii = new ItemInfo(); + ii.position = 1; + ii.object = mAdapter.instantiateItem(this, 1); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + setCurrentItem(1); + } + + public void setCustomViewBehind(CustomViewBehind cvb) { + mCustomViewBehind = cvb; + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mWindow.object)) { + return mWindow; + } else if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + childLeft = getChildLeft(i); + int childWidth = getChildWidth(i); + child.layout(childLeft, childTop, + childLeft + childWidth, + childTop + child.getMeasuredHeight()); + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. +// if (mDecorChildCount > 0) { +// final int scrollX = getScrollX(); +// int paddingLeft = getPaddingLeft(); +// int paddingRight = getPaddingRight(); +// final int width = getWidth(); +// final int childCount = getChildCount(); +// for (int i = 0; i < childCount; i++) { +// final View child = getChildAt(i); +// final LayoutParams lp = (LayoutParams) child.getLayoutParams(); +// if (!lp.isDecor) continue; +// +// final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; +// int childLeft = 0; +// switch (hgrav) { +// default: +// childLeft = paddingLeft; +// break; +// case Gravity.LEFT: +// childLeft = paddingLeft; +// paddingLeft += child.getWidth(); +// break; +// case Gravity.CENTER_HORIZONTAL: +// childLeft = Math.max((width - child.getMeasuredWidth()) / 2, +// paddingLeft); +// break; +// case Gravity.RIGHT: +// childLeft = width - paddingRight - child.getMeasuredWidth(); +// paddingRight += child.getMeasuredWidth(); +// break; +// } +// childLeft += scrollX; +// +// final int childOffset = childLeft - child.getLeft(); +// if (childOffset != 0) { +// child.offsetLeftAndRight(childOffset); +// } +// } +// } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mWindow != null && mWindow.scrolling) { + needPopulate = true; + mWindow.scrolling = false; + } + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + private boolean thisTouchAllowed(float x) { + if (isMenuOpen()) { + return x >= getBehindWidth() && x <= getWidth(); + } else { + return x >= 0 && x <= mSlidingMenuThreshold; + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + /* + * This method JUST determines whether we want to intercept the motion. + * If we return true, onMotionEvent will be called and we do the actual + * scrolling there. + */ + + if (!mEnabled) { + return false; + } + + if (!thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + // Always take care of the touch gesture being complete. + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + // Release the drag. + if (DEBUG) Log.v(TAG, "Intercept done!"); + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + return false; + } + + // Nothing more to do here if we have decided whether or not we + // are dragging. + if (action != MotionEvent.ACTION_DOWN) { + if (mIsBeingDragged) { + if (DEBUG) Log.v(TAG, "Intercept returning true!"); + return true; + } + if (mIsUnableToDrag) { + if (DEBUG) Log.v(TAG, "Intercept returning false!"); + return false; + } + } + + switch (action) { + case MotionEvent.ACTION_MOVE: { + /* + * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check + * whether the user has moved far enough from his original down touch. + */ + + /* + * Locally do absolute value. mLastMotionY is set to the y value + * of the down event. + */ + final int activePointerId = mActivePointerId; + if (activePointerId == INVALID_POINTER) { + // If we don't have a valid id, the touch down wasn't on content. + break; + } + + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float dx = x - mLastMotionX; + final float xDiff = Math.abs(dx); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (canScroll(this, false, (int) dx, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mInitialMotionX = mLastMotionX = x; + mLastMotionY = y; + return false; + } + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else { + if (yDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + + if (mScrollState == SCROLL_STATE_SETTLING) { + // Let the user 'catch' the pager as it animates. + mIsBeingDragged = true; + mIsUnableToDrag = false; + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(); + mIsBeingDragged = false; + mIsUnableToDrag = false; + } + + if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (!mIsBeingDragged) { + // Track the velocity as long as we aren't dragging. + // Once we start a real drag we will track in onTouchEvent. + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + } + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + + public boolean onTouchEvent(MotionEvent ev) { + if (!mEnabled) { + return false; + } + + if (!mLastTouchAllowed && !thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction(); + + if (action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_POINTER_UP || + action == MotionEvent.ACTION_CANCEL || + action == MotionEvent.ACTION_OUTSIDE) { + mLastTouchAllowed = false; + } else { + mLastTouchAllowed = true; + } + + if (action == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + } + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + // TODO + final float leftBound = 0; + final float rightBound = getBehindWidth(); + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + // scrollX = getChildWidth(mCurItem); + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + pageScrolled((int) scrollX); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int scrollX = getScrollX(); + final int currentPage = scrollX / widthWithMargin; + final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin; + final int activePointerIndex = + MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final int totalDelta = (int) (x - mInitialMotionX); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + return true; + } + + private float mScrollScale; + + public float getScrollScale() { + return mScrollScale; + } + + public void setScrollScale(float f) { + if (f >= 0 && f <= 1) { + mScrollScale = f; + } + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + if (mCustomViewBehind != null && mEnabled) { + mCustomViewBehind.scrollTo((int)(x*mScrollScale), y); +// mCustomViewBehind.scrollTo(x*mScrollScale, y); + } + } + + private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { + int targetPage; + if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage : currentPage + 1; + } else { + targetPage = (int) (currentPage + pageOffset + 0.5f); + } + return targetPage; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(-1); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (customWidth >= 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/a0c8141b5cc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/a0c8141b5cc300111ab8b17b137f3789 new file mode 100644 index 000000000..1fbe66743 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/a0c8141b5cc300111ab8b17b137f3789 @@ -0,0 +1,135 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/c11794ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/c11794ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3312cfa7f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/c11794ff24c3001119baa706e9d70c26 @@ -0,0 +1,33 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/e3a18aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/e3a18aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e3e3f93b9f3fe7094332bbec429571bcede114b9 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SB0XIkLn02py}Xe3KmgB?fcN{u z3OvMiHErV#k$0KenEB;EtI8a%6C0yFXUxpu+EIFUt}mysn$HY_#6vA`#$E%3=tPd+ nXMe2Lnl1EA@>|WpWjh#Ji#?9Gi^wblTEgJz>gTe~DWM4fZg4bX literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7b/f28c94ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/f28c94ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6f49d7e47 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7b/f28c94ff24c3001119baa706e9d70c26 @@ -0,0 +1,22 @@ + + + + 3 + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7c/73c595ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/73c595ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6d9dafa7a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/73c595ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/7c/c09972fa50c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/c09972fa50c3001119baa706e9d70c26 new file mode 100644 index 000000000..36d9c84f1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/c09972fa50c3001119baa706e9d70c26 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7c/e0fc70511ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/e0fc70511ec3001119baa706e9d70c26 new file mode 100644 index 000000000..cfe585cab --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7c/e0fc70511ec3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/7d/00b494ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/00b494ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3eaf4aee9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/00b494ff24c3001119baa706e9d70c26 @@ -0,0 +1,22 @@ + + + + true + false + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7d/30b892ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/30b892ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0d51220c9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/30b892ff24c3001119baa706e9d70c26 @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7d/54e897ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/54e897ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..1a532e06c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/54e897ff24c3001119baa706e9d70c26 @@ -0,0 +1,545 @@ +/* + * 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.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/.metadata/.plugins/org.eclipse.core.resources/.history/7d/e2f491ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7d/e2f491ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..76e9428beb16662de7de3bb3d9348be4760f3864 GIT binary patch literal 1160 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU0wmSG7d!(}OiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18J~chQ$R_elRdFPw;ec4DmSr_S$Lxm{1w^5AVOxdhOSw6#mu*-Q!TILX?#LYe@iQOa?I{e`UZx9V#iwBB*NKlFT13r5HiU~ z)OyPeE}nkt_xG>2E-_@*!4 zQ-90g*O?DSc|22Jv;5_#E||ssBH~GI+Rg)i3NlY6PtmkH;_P$bF_&6p;=oh_Fj0_K90GevLS= z#Ex&{-18fopXls+`pEir(5|)OmhH#CEK%CESg`jflV!q+rq_Skf<^iYCUm~tdoQiH zGvhe7N0OlO49}4Nwb?cO;IZ|v+N;i*tUdXR>)V?0gRJwGpBMQp$;pskZMAI2HPdyE?#VFh$<=%OjN_Y; zB!kvc_OmZ{-SxTpoUuatd}jEQy7CnE3T_Wg&CNYtrPT~~WUfmbd*~m_%W+dY9JyStbiIYVSNhSGu{mz*tY5fyr#S&U zR9&sK=2uepA6MJ*ynCK0mo{;K!b4t`CikV4(pycpzUuiJcQe(!&UJd(`Og*y3;Xu& zdz*8Ao98c|;9V;gMU`HY`>$E3IpMd}k-YN0{!1UF&KK8KzwcYw>t5=#TxVt1-*xe; zC7-UZgPInwXDCdwk|m}>&lDO4YwCRra zntLs+uyWevme?b=v{x~+9P8L3dzCYL!%K16KjH+7V8c~vxSdwa$T$Bo=7>o=I4RsAHbqy^;3{9DSr1<%~X^wgl##FWaylc_d9 OMGT& + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7f/20bdc373f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/20bdc373f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..50d9790d0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/20bdc373f6c500111689feaa37e8ab14 @@ -0,0 +1,22 @@ +package com.slidingmenu.lib.app; + +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public void setBehindContent(View v, LayoutParams p); + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + public void toggle(); + + public void showAbove(); + + public void showBehind(); + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7f/82ec95ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/82ec95ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..a71e1ad3c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/82ec95ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/7f/c1a691ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/c1a691ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e2aff72f483ce4cc6ccddf17331249fa612d2a83 GIT binary patch literal 1362 zcmV-Y1+DstP)?8OR-p?Vt(<)KXNk*dJ1<_`!jRpab6RMK;Rk47fDU#NEX#7yk4(~&Fr}L7DZp)K} zK)DDZgb+dqA%qY@2q7)3S*px^wsY!a9l?~jW2$HoDfOAoDc4?$q=mJH$Q@HesW|pH zEqI5t5pt#=^`ykNb$bDA+g_!6r>E#0Ebxb)V~E)@66{HSu%o+0#^7QK=<56_<*0g z4?VWXMFRkJB8s~XX6q}?LEeWW=Ef--P!X+fp` zQ#hbt=1@CWv@?Vrj0n$wG-wfB>s2&!$QdDJ0ulZgw-cuRiR{Y>^Hj3K6cvDZyr8vA z8lxp5*y$r9!v6G_XAF7`2PhmT)XW;J_(x39;8bKfgMu`e! zU+jWXwIOOF0-q>8C*JQsY~7_bBCuA z|Ap1-2&vJi9g(t&*dI@qVtrbEm_q)8uxlUymW^N&DQrSTF2REQdw9B(B*Fk-L?96w zfdFVX0=tCgq*<4>5rKwy4p!?>V+1b~mqyqhPm^M8N}pNlWK7Aa(;L|rtB1{dT%;u; z=)dm(?jeLfE6zhUB!2hW01y9MdY)1v=ujhBx3b+Xm&>Pd9KV)clx)K|j$bdA%O^}( zPFj=H`w_B~E-2}`eIdjBd_I2}hT(GvVW{|jkQIawhG7^!pU>wnc#H_%SRreOrJP6k z#f!~#`~_1^!^gPqw^)9R`+vop3DslHn(o!PiI0dTt@|45Za=)m1`%IwEW{fV$LVaF zE9RVsAMaWMjZlg;f(R_4iy{7r`=s=`3SdP<&^M)TPHqgUw5?z25;3$902*NlyMU*S zpa+j$RH$BIEX`7~H`b|A%pl=Pj|o!QHv-L&MvImjnCmfv9y@5Gq|A_|G$L4MNvqdg zg%(@J38}FG4N!(%uhEggMhM*%9HY#I^l zO-Wr$p$z~$ref=30GgqO)XJdORd}!BEq>NeB8p9{v^kJo2|NxCQwf^HCpGf6X;Wp4 zg!hgmb$FtdtQ>ASMriqL^@|$FBEhNWjw@zMktp~+Gzo9nO1w>OhBUKE#}ER(1L)vD UI+1b(O8@`>07*qoM6N<$f~tseq5uE@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/7f/e0a11e2393c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/e0a11e2393c500111b2a8b7f47e59881 new file mode 100644 index 000000000..b80918757 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/7f/e0a11e2393c500111b2a8b7f47e59881 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8/0094c70a2ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8/0094c70a2ac3001119baa706e9d70c26 new file mode 100644 index 000000000..79211512d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8/0094c70a2ac3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Window; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8/10db94ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8/10db94ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..b085952d3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8/10db94ff24c3001119baa706e9d70c26 @@ -0,0 +1,22 @@ + + + + 5 + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8/537795ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8/537795ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6ae0402c0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8/537795ff24c3001119baa706e9d70c26 @@ -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.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.app.SherlockFragmentActivity; +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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/80/529590ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/80/529590ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..43ed26d4784aa508b93551bdb0359b959bd2c91b GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nET3{Mxwkc@k8uUzCjV8Fq8;LR1* z*j37Q(x@RlU0R z*6*F+o^#JDHf2*b#j2Gf_PMBSbuGRn) zDJUkGcinCw!4`)d@_D~EMJnC5dvGXBz z^GjW6Gg4BPB{MBwxqQWN<0fP#?6J=Sj@WNJ!AH@8Kl`>9L$xnJF(@mqT0WPnt1qF1 z=Fx+;deGw@bGK5OQ+L*P{Upq+6DX1yGQbK>T~%EkI?XGa@}$o>ppa%>^8?Sie*2l7 zfHK3%D>%7|N++0Avr7*8vd@}G^Jo0fcfyUHfnsLZ&jU?a6Rn7I58e-AIzUHA66jy!AvGyBgcAIA_8&ya%2-o5w@+x^Frq z7x5uqjDu?ciVPZ-34&-=b^T>U$i3owu8N|PCmm@W9a)>Z@0e@OLVt>;Q1iTBsK`Y- zJ#Dm0pva)1q@Sv}wFUZZ<(6Yki*muoJ=kjDtmVDYq#tH=k$<|@5vTpkf+%-~CzQJb zDj5=FGBxvks&SW*YJTnCqA2*7ySf013>jGQpITpe;Jn|eigLRhZQhTXHIx~a$pm$C z{nZbIsz13R7nL1tHd-@KF*$Um(og?cC1;!x<)VYeI|B_UB@HdgHw5UWlj@?}cDp+O zMal|-j9w2i9i`?Cb8^v;J)JZZ3@FG_LfsGv{MVdZZorO4w{8Y134%<%0TH$=m)%OW z_@u(SziK>nET6ihG`KOcU?%zJh~m2+ycN)r5;qQq+h%%Xy;f)Ejn0a3UnsuS^+vZqWP#0th z#x}@k!|oI0qU+rNRV>J4GUFR$v|a9z%jMoM-5IE6CMAy{ll?bZ%p5f-7cDwzt|L%b z^86*Y-fp1pM3X+OAj(~JqWJ*PYCpbZCY5MgZSAj)V(>vz$zUg(ZywPKsOqx1Or~s4 ztCPVxWShrQgx&N<^IZW2u9-7hOofKj5BzxpoW= zdO}GqH|+&2+j}j6LUh@cv}2FCzaLvtWZ?^TwHb8;v&L-C`+P^-e$fT!yBz5Da{oL7hj@h;h3%R$P7X_J;dmT2? z8&V8*_<~22M7c%3b3D}BjlNwczv7fZds1ebGU8;svesTmESU0X4=BlHYF_eOt8iaY zL0I~yq8N;M$m4dU73%)xM=srNe&@#dxWo1;CZw8+{^f0pouFbc zV#*`lZz%0)HGlQf<_c&{Ktx7;z}?CzodgvZopY&OUp7)Q;eaFVO?})iuy4L9j zyLs2K^qSz1EvYP7>Ws{|~_-QddT;IiL%she&}m+lY?b~t3u zik_CPT+O0+6?K`iA!CLOr{nnY$OW(ay)*42s|TRe$lC9I+YPJ$b-IG8H~q!myML>= zroa>ruDyrb zV`&jHgSNQCgmI$=lu=hRYuXKOo3_xM&-4jsmA;l<3@^Ph&(-?zXM#=Hludb0$^QZH zs3&Vcm*{c;001R)MObuXVRU6WV{&C-bY%cCFflPLFgPtTGgL7)Ix{mmGBYhOH##sd z?sz9s0000bbVXQnWMOn=I&E)cX=Zr$HaasiIx;gYFgH3dFrOu# z?f?J)8FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?002ovPDHLkV1l}_ BPJaLZ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/80/92de89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/80/92de89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..bd19140ab --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/80/92de89ff24c3001119baa706e9d70c26 @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/80/d17a8aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/80/d17a8aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f4ff16be7323486b7fcd49b3e9bb07816a75b53c GIT binary patch literal 2862 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 parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/83/5085db29f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/83/5085db29f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..af16c964f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/83/5085db29f4c500111689feaa37e8ab14 @@ -0,0 +1,1185 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/83/6007dfe223c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/83/6007dfe223c500111b2a8b7f47e59881 new file mode 100644 index 000000000..cca867ff6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/83/6007dfe223c500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/83/f21b92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/83/f21b92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3015d307088f12d52a9e99ff4575fd2153127e5b GIT binary patch literal 381 zcmV-@0fPRCP)hG*08Y#N?T!?S64w!;lKvy+*1?>p3RGdlx#190x$dzj&7b^-9QUftoB@I?dG z(l;!l|3;oEFaA*ajtwD8hd-6>9*;+5M`bO2!%}+FXrQS0p3;u)|QJUO}XO$+G;+dssck%4fw5xbU zX__uxRhp)XSC*#P;_m>iSbo@k`^^CW{9xcU{p|2h0AG{O_A~&$L7!btFK9(XM7DX= bKfeD1Etg?&Fp}qT00000NkvXXu0mjfW#pxI literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/83/f2fd96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/83/f2fd96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..5a8099832 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/83/f2fd96ff24c3001119baa706e9d70c26 @@ -0,0 +1,234 @@ +package com.actionbarsherlock.internal.view.menu; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ActionProvider; +import android.view.MenuItem; +import android.view.SubMenu; +import android.view.View; +import android.view.ContextMenu.ContextMenuInfo; + +/** Used to carry an instance of our version of MenuItem through a native channel. */ +public class MenuItemMule implements MenuItem { + private static final String ERROR = "Cannot interact with object designed for temporary " + + "instance passing. Make sure you using both SherlockFragmentActivity and " + + "SherlockFragment."; + + + private final com.actionbarsherlock.view.MenuItem mItem; + + public MenuItemMule(com.actionbarsherlock.view.MenuItem item) { + mItem = item; + } + + public com.actionbarsherlock.view.MenuItem unwrap() { + return mItem; + } + + + @Override + public boolean collapseActionView() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean expandActionView() { + throw new IllegalStateException(ERROR); + } + + @Override + public ActionProvider getActionProvider() { + throw new IllegalStateException(ERROR); + } + + @Override + public View getActionView() { + throw new IllegalStateException(ERROR); + } + + @Override + public char getAlphabeticShortcut() { + throw new IllegalStateException(ERROR); + } + + @Override + public int getGroupId() { + throw new IllegalStateException(ERROR); + } + + @Override + public Drawable getIcon() { + throw new IllegalStateException(ERROR); + } + + @Override + public Intent getIntent() { + throw new IllegalStateException(ERROR); + } + + @Override + public int getItemId() { + throw new IllegalStateException(ERROR); + } + + @Override + public ContextMenuInfo getMenuInfo() { + throw new IllegalStateException(ERROR); + } + + @Override + public char getNumericShortcut() { + throw new IllegalStateException(ERROR); + } + + @Override + public int getOrder() { + throw new IllegalStateException(ERROR); + } + + @Override + public SubMenu getSubMenu() { + throw new IllegalStateException(ERROR); + } + + @Override + public CharSequence getTitle() { + throw new IllegalStateException(ERROR); + } + + @Override + public CharSequence getTitleCondensed() { + return mItem.getTitleCondensed(); + //throw new IllegalStateException(ERROR); + } + + @Override + public boolean hasSubMenu() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean isActionViewExpanded() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean isCheckable() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean isChecked() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean isEnabled() { + throw new IllegalStateException(ERROR); + } + + @Override + public boolean isVisible() { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setActionProvider(ActionProvider arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setActionView(View arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setActionView(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setAlphabeticShortcut(char arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setCheckable(boolean arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setChecked(boolean arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setEnabled(boolean arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setIcon(Drawable arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setIcon(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setIntent(Intent arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setNumericShortcut(char arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setOnActionExpandListener(OnActionExpandListener arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setShortcut(char arg0, char arg1) { + throw new IllegalStateException(ERROR); + } + + @Override + public void setShowAsAction(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setShowAsActionFlags(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setTitle(CharSequence arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setTitle(int arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setTitleCondensed(CharSequence arg0) { + throw new IllegalStateException(ERROR); + } + + @Override + public MenuItem setVisible(boolean arg0) { + throw new IllegalStateException(ERROR); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/84/622d93ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/84/622d93ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..33e2dea0d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/84/622d93ff24c3001119baa706e9d70c26 @@ -0,0 +1,38 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/84/a4c993ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/84/a4c993ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..1e1c7022c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/84/a4c993ff24c3001119baa706e9d70c26 @@ -0,0 +1,42 @@ + + + + + Navigate home + + Navigate up + + More options + + + Done + + + See all... + + Select activity + + Share with... + + Choose an application + + Share with + + Share with %s + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/85/4094b6c125c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/85/4094b6c125c3001119baa706e9d70c26 new file mode 100644 index 000000000..ff095c53f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/85/4094b6c125c3001119baa706e9d70c26 @@ -0,0 +1,1178 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/85/f0c88aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/85/f0c88aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a16db853e94af78c0739d9b89b578e2a8021c856 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Sd^}woLn02py|j?`fP(zopr08IHUH2?qr literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/86/108d5a6d26c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/108d5a6d26c3001119baa706e9d70c26 new file mode 100644 index 000000000..b2e9db5f5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/86/108d5a6d26c3001119baa706e9d70c26 @@ -0,0 +1,772 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/86/20f6d7cd2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/20f6d7cd2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..d4f43c042 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/86/20f6d7cd2ec3001119baa706e9d70c26 @@ -0,0 +1,643 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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) { + return new ActionBarSherlockCompat(activity, flags); + } + + + /** 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/86/33b892ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/33b892ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7010bcce9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/86/33b892ff24c3001119baa706e9d70c26 @@ -0,0 +1,23 @@ + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/86/421b89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/421b89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..5ca7d6247 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/86/421b89ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/86/80288cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/80288cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..1c269205e874bc6addc308efe5be4fb7c5da0edc GIT binary patch literal 917 zcmV;G18V$CDOJO>Ym5d24oA2hD9A9kkZ#C-ocYxQulY$%dG^s1`jD zWrBMf{hI5z?Ps6d&cAMwxpu9tAQSLC;sV+l?CI!atlqGv_K~X}S&7D6#irA$G%zcr zGa^}SvXODrvrsWB#ZkB-c}-Y}>Q0!#L#9IQCX$ZI#7DnF9fJ8(R=8iR{NJvIR3GfdBS0fGXvSYugM@B@Fy~s_l`Jy)|ccqHxmVzApHz{x4N{y z#Xj0V$LH=@zsWY)$4Z)6--edG^VYGh&b$}$F3XeLt5=Uu0`p37@FaypB&t$KuAm9R zq*|yt7WOdr(m%g{dU1bs0-qy(nh~3JDc<<|K^(;cR4G!8UrKd|p;N zi5zZftW#Kk#vM}fdS+hLQ#;Dq?H?_`8P1nhqmR=j>Au${MMR)hh&5HCA z?cjx6pHV1ZFFx`ra1m|YMALE$u3RAxZp(6Eus@DJwzn!G7Cw2Mm%K&AN5Ia`DuuPd r`dvHM#yxB2nYDo;0!e2cs)*3P7gB8$K+RT%00000NkvXXu0mjfr&_ZI literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/86/e4a18aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/86/e4a18aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..1e39572224b24a81ed4d73923280ba2724dbaf6e GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Sf;?RuLn02py|Iy(L4oIp!})_Q zZ}wlfoYKNk`|wbZR*CB+2cd0Do4#G+S+1#YsD)El&1Z%|BAjt`!_S2)TNKYc{m-!5 f_v_(jT(cfAPEEXE)c4^Y$T|j3S3j3^P6 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/87/10efd0432ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/87/10efd0432ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..d28814439 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/87/10efd0432ac500111b2a8b7f47e59881 @@ -0,0 +1,201 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + private SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/87/324790ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/87/324790ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..2283b4c01f31c24c241101989a028a28e662ff2d GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#v+DPvC;#}JFt$r%|L2@FmD6{OlE zCs-P=E^ay;FECA@!GWvmzw+t@{SPuqdTbmsKK4nJ zaCd?*qxs3xYk`73o-U3d5>u0Z{Qqyy%*=eaUL!352pYN+StcB)SJP>#V9b+U;=RED z2qf|=A9d?gTyt;ZSzN%FWhK6zW!r_Lk7KrU{Nfk8lS< uMnfl1c4A|rBX^f%!~&s(1*$LFm>5oL2|PB@cz*+E5QC?ypUXO@geCw>u`ROz literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/88/00dac57f48c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/88/00dac57f48c3001119baa706e9d70c26 new file mode 100644 index 000000000..7302ac1bb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/88/00dac57f48c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends Activity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/88/01f08aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/88/01f08aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4af38fb70b55ed57b39d11944a0eafd47a4af868 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{< + * 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/.metadata/.plugins/org.eclipse.core.resources/.history/89/33d68dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/89/33d68dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..df2d3d158e201f4b5bc8f478bfe194c819c762d1 GIT binary patch literal 466 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 V)0&M6I|u*(002ovPDHLkV1mJeC(Hl< literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/89/743698ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/89/743698ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..a340a4291 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/89/743698ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/89/907a82e930c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/89/907a82e930c500111b2a8b7f47e59881 new file mode 100644 index 000000000..e8195659d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/89/907a82e930c500111b2a8b7f47e59881 @@ -0,0 +1,41 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceManager mManager; + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context, PreferenceManager manager) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + CheckBoxPreference cbp = new CheckBoxPreference(getContext()); + cbp.setTitle(title); + cat.addPreference(cbp); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/89/b0f093ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/89/b0f093ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..c6e8b6624 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/89/b0f093ff24c3001119baa706e9d70c26 @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/89/d0305c4a3ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/89/d0305c4a3ec3001119baa706e9d70c26 new file mode 100644 index 000000000..6a5ddf1ef --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/89/d0305c4a3ec3001119baa706e9d70c26 @@ -0,0 +1,20 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8a/11888dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/11888dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..5dc6f804aea8ca344275ac6eb497b6bfe0f117f3 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQd*uajv*T7lQS|h5*V8PD@dJb xGfWV2j%0Xds4&4P&{4SYp+J&{BRiiZ!)425)ejdW>;mdy@O1TaS?83{1ORBM8sz{0 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8a/40355f4f5dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/40355f4f5dc300111ab8b17b137f3789 new file mode 100644 index 000000000..de7db8e29 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/40355f4f5dc300111ab8b17b137f3789 @@ -0,0 +1,207 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8a/c0af62282ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/c0af62282ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..d8b9571fd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/c0af62282ac500111b2a8b7f47e59881 @@ -0,0 +1,151 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + + /** + * + * @param i The margin on the right of the screen that the behind view scrolls to + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8a/f0127fde52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/f0127fde52c3001119baa706e9d70c26 new file mode 100644 index 000000000..8f733bc81 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8a/f0127fde52c3001119baa706e9d70c26 @@ -0,0 +1,145 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8b/0048e819f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/8b/0048e819f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..0b0cc760f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8b/0048e819f8c500111689feaa37e8ab14 @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8b/23af8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8b/23af8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..31e49894adaca85c253cfb262a93299c3d25489d GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%&YmugAs)w*Gcqy~4zxBtu(zuW zGMHg-@7EW5UBeRx4_{gI--K 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/8b/92c08eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8b/92c08eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..9458668f023082dfc8d3f49a6c2cecb466b058f7 GIT binary patch literal 1336 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfizez!?|}o;S3Bc4xTQKArXh)PV>&05-QPl|NEJxmot~Y-O?6i zSoE4VV50(~VFweNuSbvJvDU(em!@_Gy7>C|bVSGQC`nC9V$w5l5%vk()99rs+U}Ie z#gw!%)oQMv{^i7d*IlE3+&<@%p0;w&$@ypMpUwGhdH?7B;(g3_F4o8CEW7NhbVSM} zqSCB_!=qSev5fPtyGqA?asRjFZK+%zRmuM+<~%bCV-%Sz^PrNaaE@g9foeX-u+5!sBTi~HIW*n>)Nj7ol{rZ9-4nMT zoXaYtmP_*AdKAZAlk-GvO?pRyl>Mh8`+Nc$HY$`qPPFQpUN|M($@0weFZ=q>-Z|;k zASrkFqq&&t!{{3mN^Z2R{c=#?a3WtQ7weUk>iG|Zq$QT}pSIkU{^CTFT;9KIrmSnq zpS&#=uRnCsOK0id8}?`PEg3d8`7hvXW$egc*J6#mVt#e9_pb9<_ciuE6F6vP_s!9j z(P7T51!|6-rEWn-Z!t5pRZaT>G0pp*?o69U6_j*jr;%AU466Xxt@KxFWQ#C`^3eSLB zzg~IIvuD^d>#3#GLD3I7lf(noYc&h)3hc9G_+WKhHsZ8LoPy9%C4Uce+&;>2@bsHn&Pv7xpmx^;r<{ zyLsxJv!X1=e=@5Da9q$kdPVo-a@|{nyH;q}t$!wG=kQ6b{@GG-@nhR69M(itUsa0= zOaD6e(QK|M^YvG#-Ci16Wb}90IdQSr=Hj%|Go@_TnpsY6``Z0AtH!%8u6<>P+?BM| zqEoJFmfFoDzId)kH^*J-T zifmnxrK6#lyVy%(-Id^*OWp5Z{O|Cesp8<@8Fi79bbtkmYKdz^NlIc#s#S7PDv)9@ zGB7mMHL%n*v 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/.metadata/.plugins/org.eclipse.core.resources/.history/8c/200b8dcc24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/200b8dcc24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ff827205f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/200b8dcc24c3001119baa706e9d70c26 @@ -0,0 +1,1162 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/8c/61bc90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/61bc90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..df0121bb353f5b30b732b715a758ea6fcb3d5220 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nET3{Mxwkc@k8uUzCjV8Fq8;LR1* z*j37@e9?;BET59A4}CU%C?X?h==XH3&Ch$+?qA(hd6mJ@0WUC9xN5g~;_G=gEfo|L i>YLYC-!V(AVEFG+v!>way|q9)89ZJ6T-G@yGywpFG&bP? literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8c/70d9149024c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/70d9149024c3001119baa706e9d70c26 new file mode 100644 index 000000000..a048805ec --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/70d9149024c3001119baa706e9d70c26 @@ -0,0 +1,217 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + ((ActionBarSherlockCompat)this.getSherlock()).initActionBar(); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8c/90de89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/90de89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ee497a239 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/90de89ff24c3001119baa706e9d70c26 @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8c/b07f91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/b07f91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e4b33935a3aa4f1af3fa9e9e199b5c47d43f4b74 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn2vPZ!4!jfu$y_kK-b literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8c/d0c20e8af8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/d0c20e8af8c500111689feaa37e8ab14 new file mode 100644 index 000000000..45bf582c5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/d0c20e8af8c500111689feaa37e8ab14 @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8c/d0eb8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8c/d0eb8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c65f443e338f4c5e93dcc83bacc9c8ed61d776d3 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%9-c0aAs)xyUfRgZV90aWq3=2C zp8pzu)R>=evwJLPDoBk{4*AEnmdKI;Vst0H2gA*Z=?k literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8d/30f44a092cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8d/30f44a092cc3001119baa706e9d70c26 new file mode 100644 index 000000000..dc3e30c71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8d/30f44a092cc3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/8d/9007c34315c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8d/9007c34315c3001119baa706e9d70c26 new file mode 100644 index 000000000..8487d9b72 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8d/9007c34315c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/8e/304790ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8e/304790ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6da264db26b5debc433e570e454f7ad596d3609c GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETbWaz@kc@k8Z*Aml2;gwNxP9_w z>q*543$-17oYd6QwPclDxvFIP6Y06uZ3-`2R5T~}Ha6e^YubHkRDB$o9=Xj@xc>Lb i$;LIUf5PjFDj6>?G+3v-_OK(+N(N6?KbLh*2~7a3Fg*4E literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8e/50e172181fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8e/50e172181fc3001119baa706e9d70c26 new file mode 100644 index 000000000..38f835ec2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8e/50e172181fc3001119baa706e9d70c26 @@ -0,0 +1,1145 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + initActionBar(decor); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/8e/90126ef42bc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8e/90126ef42bc3001119baa706e9d70c26 new file mode 100644 index 000000000..21ab9c1e6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8e/90126ef42bc3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8f/02f08aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/02f08aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d32f74cf4c6013a223fd25577c6d655f7f8c114d GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{<kjg^D5fnx&0glSHJj>3%>1Jqp^q#PeS;bnL@oAJ;NJ=s*Cb_P#ZKbLh* G2~7YBfgFPX literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8f/426e90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/426e90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..131d1030c9d5b447ef62fc8e336d9d3950ff7519 GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#v+DJxGG#}JFt$r%|L2@FmD6{Ok@ zwtT#{-1s4r1MA|Z!|?(x4J`lv|6k8`NJHzTnuV0CvcJHrKmQJQDKT8Re5&^Sxg#LM O7(8A5T-G@yGywoD=q9NE literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8f/80ec95ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/80ec95ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e9215e7f8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/80ec95ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/8f/a25891ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/a25891ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..690cb1eb61f6bc4ce58e5c1fb30304db69393bc7 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn2vPZ!4!jfu$y_kK-b30u5yFboFyt=akR{ E00Z(eO#lD@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/8f/f05f6a694ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/f05f6a694ec3001119baa706e9d70c26 new file mode 100644 index 000000000..030a32091 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/8f/f05f6a694ec3001119baa706e9d70c26 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/014392ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/014392ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..29036b907a231d6b0d4e25d906eccd2e176455c2 GIT binary patch literal 671 zcmeAS@N?(olHy`uVBq!ia0vp^dO+;N!3HEX`k#maDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9q_DOpcx|jv*P1Z)f>u3p>g<+)ulGcHZsoOUd0`v$ideb3Xs*rv6J! zg}R0?Ejbavstni13%M+(h~#=Y?=G{+sY|c-R?LyC;M~J_EGz53I-4BR z+cU4@A4T%4{LQ{7{nooe_R?;9Ufq56+wp;!Z_W|LdHU^V zuiix!E)rt*mg%eid+||lw)K3kxzR2XQeoHKTo0e>Tz_Z7KF;I+KDl^G6{a%9AKj}v z@Aq1v55LRoZXbD)<16^lF!*Li$^7}+)mu{zFEMCaSs}k;w&aatvA+!FKCV6>P_Fen z(L?roLe!sxPkWei7+T9&rtD<0W7^%ZdcE}hdZyQpKhHVIBAEwFVGN$GelF{r5}E)^ Cjyh@p literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/2073b0f72ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/2073b0f72ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..f933c8c5f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9/2073b0f72ac500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/305425242ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/305425242ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..09dfe13d5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9/305425242ac500111b2a8b7f47e59881 @@ -0,0 +1,143 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @return The scale of the parallax scroll + */ + public int getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/507ec6064fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/507ec6064fc3001119baa706e9d70c26 new file mode 100644 index 000000000..c59822c67 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9/507ec6064fc3001119baa706e9d70c26 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/60759eacf9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/60759eacf9c500111689feaa37e8ab14 new file mode 100644 index 000000000..ab63acc71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9/60759eacf9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingListActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9/c01794ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9/c01794ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..63b12f7f3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9/c01794ff24c3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + 55% + + 80% + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/90/b02c8aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/90/b02c8aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..769463b369a5185ba2d2fdf26abf058086ebcd08 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S!aZFaLn02py|Iz^fCC51!MDwC ze!c%VXGhEQ)_dJsezHtpNMD|7Dac@a*_ZJyulFV2w{5C|YCbaz5)ZX-3ak0tIJ#lm tp_aeGY*)k&iW*FhzahTiJD1r}=BlLiI{(TJ=>e@^@O1TaS?83{1OUp mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + CheckBoxPreference cbp = new CheckBoxPreference(getContext()); + cbp.setTitle(title); + cat.addPreference(cbp); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/91/40c38c6824c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/91/40c38c6824c3001119baa706e9d70c26 new file mode 100644 index 000000000..a49d11174 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/91/40c38c6824c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/91/40d25635f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/91/40d25635f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..0a6aeaf15 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/91/40d25635f4c500111689feaa37e8ab14 @@ -0,0 +1,1193 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + if (decor != null) { + mDecor = decor; + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/91/e0f09c4a1ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/91/e0f09c4a1ec3001119baa706e9d70c26 new file mode 100644 index 000000000..8c46f1d65 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/91/e0f09c4a1ec3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/93/3047871c16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/3047871c16c3001119baa706e9d70c26 new file mode 100644 index 000000000..aa7bf6f43 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/93/3047871c16c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/93/50d573254ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/50d573254ac3001119baa706e9d70c26 new file mode 100644 index 000000000..f2aa64d2d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/93/50d573254ac3001119baa706e9d70c26 @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/93/52e897ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/52e897ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..319c9ab83 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/93/52e897ff24c3001119baa706e9d70c26 @@ -0,0 +1,699 @@ +/* + * 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(); + + /** + * 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/.metadata/.plugins/org.eclipse.core.resources/.history/93/72728eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/72728eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..460ec46eb0786706610e21ac9097de489cedfc33 GIT binary patch literal 651 zcmV;60(AX}P)!1&^00004b3#c}2nYxW zdZ_-Wf*5)VugS&t+23J}V*z%DOHb#W|`Z#l>;cJ*L_P;jGoKD8nX4Z`xH*Q>s zTvTl`b;%gqS1znaOc|u@tz3t7=|UK<9Hr>BJ|D1%4AOYzE>c>YASL1(e+Y^`_iG?7 z1UL~EK(|`0e*W#*UXt~C{TfUweyI5sSBLVgO?u)p&e9+4(C=i^T1GuQJ|j^LdEE0 zfZFjzm@Nd117_`XxKDqSoJXh_wG-}tW_yHE!!B|TSvyio<6k9eTgoG9O0aTdZJ81x zmbul8Z%fpkT#Wc{ND1L@No&VX#iPVF7hx`c0JdkE;3e2%ZBQYi%Oe#dj=&z+_I>|? zOJi$dCv)FoZJG3n&>Qp|;vSo*JOkf=A5uR{`;uV-QwsX>Ho!a31HXV*se5TxFFA=4 zo=3!%#5;D2+DO|6R;c8b^-B2j{s4XhZw!t1m&l3O!HmBwHn=!)kb6yF?kI1MVX*Vu z<6hz)DH{^YBPWDzO$|0isCW3@P>L98oO;C$E5=4jGEPjLS?XZ=13IvJLaC?O;nLn? z=e?6_T^b`&$N3sK+o1N3^-DyB&=+_N>geY)_rHdJwBJ%s{^4(_WBZ5MLQM53U4RfX laXn(LVYMe-Njr@(d;;;gyUim^Wn%yU002ovPDHLkV1m`SB-{W1 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/93/c05cdb825bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/c05cdb825bc300111ab8b17b137f3789 new file mode 100644 index 000000000..f93fed70e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/93/c05cdb825bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/93/c0d88cd2f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/93/c0d88cd2f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..228e1cac5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/93/c0d88cd2f9c500111689feaa37e8ab14 @@ -0,0 +1,40 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/94/00f4563952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/94/00f4563952c3001119baa706e9d70c26 new file mode 100755 index 0000000000000000000000000000000000000000..3329b6b0a8b8165c054bbe28a45fdcb32a7fab38 GIT binary patch literal 1915 zcmV->2ZZ>EP)#H2P2?#Y-whXf*`XMiDeMrU~)EnzTu4QY319 zP_#r1SXyKI0I4wwjn<@r)}&q+5OpF(wZ{K?99&0Ip;gq znO(!^=&15MH{48ZPxM_j^R|w_j=P$^~$$8ODqm4#EeRH$3vo9Ns#?R5d9rN%wHga=wQ-+6!a|Q+mmIej}{tVI; zddUrXZ{ls+w)uN|d;es$T4NtQdeqn6-rfr#*YW*}mX?;XvuDq?>lMm#>({Rj1iyD+ zkaaLdLQqhU72VR?+uHzsb5EQ&(XEG{ZVvG9*oZ#ojZdGqF%06GU2UokW^6d4v4W&v*tcqkT&Md|A5vSFML9+w^Q zkv-iCjEsyd_VxAkLsu|YC=kk6f`fxC-QC@BP$UY%Ghx{)umo@wfsD08B9$45}cwT^%VLAk6;${$^O#x2>&h z6|9@GYuBz@*xO0)SpO8~XXA`F6^0Rvq@%@6CX>pOeAy@i^b6E4IzDuHVDH|&MhKWg zA{NmyEU8)%Np6gain1ca9zcsAhkxh7G zFMipwWv1%t>LF)3=u!YKjfb_OC`g<1B9Nnm04#VAKtHLhtbABiRn<=bsi~g^XFPa55I50)okncu(EFef!F11>+J- z1)nznOr;YV?I<+N4e-)+q3KcpLS7c;1Sy?soNF6PEJ8?4UhO(!e<#YNuXc^#*|bW~ zNPqP?+OuQLohkrpM!=;rQ9YE%$jEMl(y$05c+N#3&RIopAuU1}y(vQT^72*zd@}d6 z=ee&n0K7ax8I*;2%+{@2qlL#}BRo5TXT*No=r!1? zId$sPV#o>RIY&+RTS&viaQgJ=@9y5cyOcoe0b-&8jB@+-?K;qn#>B)d1WKCaizY#e(9b)d;XqO8o~CaPCa0UXcXa53_!2K3o5->l7J9m3T|B93q9fC;j>7O zwSIWff>2U;kx3Ie<`t?}@p!?Lk1HNf>B`H?tKo&$1PnkZp`oFDc+gz{unH(y*V@|p z2fiB++u;aBdTd>PfB&NU_wO4~QiW8p*=(0GGc(ESX+k~Obv$v!1LQc`)6+vQB-0DD zI+FY<)^@C2yY`YDkq@wT75%`OGiS0QA|gI+Zf=f*)fxLk^eB1Sp>w+Ass~iYWo2a- zQ1h1q{5iZv-@hSf!z2AiCR@xS9hzV zq$C}o^9{o6fUDpM!YvQrm1@G}6jWGP*n-EG886XdSo~eoZxgEy?*ul+JHkZ4FRd<= z*xhk)afg_&M~@zzcmDkOn-vumPZL6=(Es6<0$MTnom_xW*$=CF@g6|(KB@P-ZRrVC zpr)p#4tQeCv17-owe+se-3lQQx^d&i09ZLcIy%~m)rdDP>%BCVOL~JH>w$>9vA9^;-pJ%e4qPoNDr(RR($P7O zC~)}j;WmITffC&kE)*(1RyeW~Jl;#Kcyb)VwqsX0Lao{JhyvtSTU&boZ=x@8Gk4)h$ z5l@WIP(DlCLi`M|M->p>`}Xa#A)FS%+We2R4<++QRGlAS`3^bbsc}LS@Dw;bd_0x| zdW22HnMnmE!m8upIq8A%SZgBAPI_P>tU4Z^e*(_ulLD}XD3t&J002ovPDHLkV1jO* Bow@)3 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/94/03f08aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/94/03f08aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..66adffed632f0f6267afe6dc2f518adb6a83ca4a GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{<*?y}vd$@?2>|OKBsl;8 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/94/6068e9cdf9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/94/6068e9cdf9c500111689feaa37e8ab14 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/94/6068e9cdf9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/94/63bc90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/94/63bc90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ef58e292400804c570a4f2625a84e8d89d753329 GIT binary patch literal 1256 zcmVP)*??YAL*8RA!9349xlT>xKhZ*TuOWygd# zhMSw4-+>nR4|oBdfevVZemK?-$NFIlA%uRlS^35{( zT}BvQM-}4JU^TCykr2oTLIAHf!c^TL#7FZcO&)6muOXR1oSWPv&umVS5o82$Zr-fN zk`dDBCfi`z0U^#wNtd3EN92s)2|wM}$Il_i3*tO zZzIHMY1MHBL9_X5;L0Lh3G+o#6`1lChHH>!a6(t+YFvC=h;N2i? zC^SveHcd0P|3aLE^?J>Ey>4+d>6~7yXVZ6$a@Y*O5UUs;9v=R>yuAG5;^N|Rxm;3J zuZ1b@eB(On(r^e9wKJbNp28e&n@N_d2GnbM<5D-1lIySah4s=KKBq{SW3B z%2^H`-F018)%I~7x8)Gy8mM+H)TN2vhWOR&x92ZSjBBgLHiU?zvp;d{A7fm*v}M1x zX~%x8)7C_L{)@R^oaqd!)oN!DFC)aKzt_REShk-T8iK9Rb6LbQf(-Gw@kSa46EaTh z%y&R8^@=@ zwncC%{50n30vSPAQo*L1XM}Xfl-3rb`wUa32MxO!VJMirLfK}97<+S0pTrjqGlEwj z%M1eip^VKCo*}%UQ!Wz#`8TCq5!Q8G0j12aI3j{y6UYF 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, mDecor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/94/e26594ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/94/e26594ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..03473572c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/94/e26594ff24c3001119baa706e9d70c26 @@ -0,0 +1,12 @@ + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/95/309ee17f2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/95/309ee17f2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..81b839ac7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/95/309ee17f2ec3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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; + + public final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/95/612d93ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/95/612d93ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..657aeb794 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/95/612d93ff24c3001119baa706e9d70c26 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/95/d0c5554c5dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/95/d0c5554c5dc300111ab8b17b137f3789 new file mode 100644 index 000000000..1313093f9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/95/d0c5554c5dc300111ab8b17b137f3789 @@ -0,0 +1,208 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/95/e064c92585c2001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/95/e064c92585c2001119baa706e9d70c26 new file mode 100644 index 000000000..cf81e402a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/95/e064c92585c2001119baa706e9d70c26 @@ -0,0 +1,338 @@ +/* + * 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.slidingmenu.lib; + +import android.database.DataSetObservable; +import android.database.DataSetObserver; +import android.os.Parcelable; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; + +/** + * Base class providing the adapter to populate pages inside of + * a {@link ViewPager}. You will most likely want to use a more + * specific implementation of this, such as + * {@link android.support.v4.app.FragmentPagerAdapter} or + * {@link android.support.v4.app.FragmentStatePagerAdapter}. + * + *

When you implement a PagerAdapter, you must override the following methods + * at minimum:

+ *
    + *
  • {@link #instantiateItem(ViewGroup, int)}
  • + *
  • {@link #destroyItem(ViewGroup, int, Object)}
  • + *
  • {@link #getCount()}
  • + *
  • {@link #isViewFromObject(View, Object)}
  • + *
+ * + *

PagerAdapter is more general than the adapters used for + * {@link android.widget.AdapterView AdapterViews}. Instead of providing a + * View recycling mechanism directly ViewPager uses callbacks to indicate the + * steps taken during an update. A PagerAdapter may implement a form of View + * recycling if desired or use a more sophisticated method of managing page + * Views such as Fragment transactions where each page is represented by its + * own Fragment.

+ * + *

ViewPager associates each page with a key Object instead of working with + * Views directly. This key is used to track and uniquely identify a given page + * independent of its position in the adapter. A call to the PagerAdapter method + * {@link #startUpdate(ViewGroup)} indicates that the contents of the ViewPager + * are about to change. One or more calls to {@link #instantiateItem(ViewGroup, int)} + * and/or {@link #destroyItem(ViewGroup, int, Object)} will follow, and the end + * of an update will be signaled by a call to {@link #finishUpdate(ViewGroup)}. + * By the time {@link #finishUpdate(ViewGroup) finishUpdate} returns the views + * associated with the key objects returned by + * {@link #instantiateItem(ViewGroup, int) instantiateItem} should be added to + * the parent ViewGroup passed to these methods and the views associated with + * the keys passed to {@link #destroyItem(ViewGroup, int, Object) destroyItem} + * should be removed. The method {@link #isViewFromObject(View, Object)} identifies + * whether a page View is associated with a given key object.

+ * + *

A very simple PagerAdapter may choose to use the page Views themselves + * as key objects, returning them from {@link #instantiateItem(ViewGroup, int)} + * after creation and adding them to the parent ViewGroup. A matching + * {@link #destroyItem(ViewGroup, int, Object)} implementation would remove the + * View from the parent ViewGroup and {@link #isViewFromObject(View, Object)} + * could be implemented as return view == object;.

+ * + *

PagerAdapter supports data set changes. Data set changes must occur on the + * main thread and must end with a call to {@link #notifyDataSetChanged()} similar + * to AdapterView adapters derived from {@link android.widget.BaseAdapter}. A data + * set change may involve pages being added, removed, or changing position. The + * ViewPager will keep the current page active provided the adapter implements + * the method {@link #getItemPosition(Object)}.

+ */ +public class CustomPagerAdapter { + private DataSetObservable mObservable = new DataSetObservable(); + + public static final int POSITION_UNCHANGED = -1; + public static final int POSITION_NONE = -2; + + private View mBehind; + private View mContent; + private LayoutParams mContentParams; + + public void setBehind(View v) { + mBehind = v; + } + + public void setContent(View v, LayoutParams params) { + mContent = v; + mContentParams = params; + } + + /** + * Return the number of views available. + */ + public int getCount() { + int count = 0; + count += (mBehind != null)? 1 : 0; + count += (mContent != null)? 1 : 0; + return count; + } + + /** + * Called when a change in the shown pages is going to start being made. + * @param container The containing View which is displaying this adapter's + * page views. + */ + public void startUpdate(ViewGroup container) { + startUpdate((View) container); + } + + /** + * Create the page for the given position. The adapter is responsible + * for adding the view to the container given here, although it only + * must ensure this is done by the time it returns from + * {@link #finishUpdate(ViewGroup)}. + * + * @param container The containing View in which the page will be shown. + * @param position The page position to be instantiated. + * @return Returns an Object representing the new page. This does not + * need to be a View, but can be some other container of the page. + */ + public Object instantiateItem(ViewGroup container, int position) { + View view = null; + LayoutParams params = null; + switch (position) { + case 0: + view = mBehind; + break; + case 1: + view = mContent; + params = mContentParams; + break; + } + if (container instanceof CustomViewAbove) { + CustomViewAbove pager = (CustomViewAbove) container; + pager.addView(view, position, params); + } else if (container instanceof CustomViewBehind) { + CustomViewBehind pager = (CustomViewBehind) container; + pager.addView(view, position, params); + } + return view; + } + + /** + * Remove a page for the given position. The adapter is responsible + * for removing the view from its container, although it only must ensure + * this is done by the time it returns from {@link #finishUpdate(ViewGroup)}. + * + * @param container The containing View from which the page will be removed. + * @param position The page position to be removed. + * @param object The same object that was returned by + * {@link #instantiateItem(View, int)}. + */ + public void destroyItem(ViewGroup container, int position, Object object) { + ((CustomViewAbove) container).removeView((View)object); + } + + /** + * Called to inform the adapter of which item is currently considered to + * be the "primary", that is the one show to the user as the current page. + * + * @param containviewer The containing View from which the page will be removed. + * @param position The page position that is now the primary. + * @param object The same object that was returned by + * {@link #instantiateItem(View, int)}. + */ + public void setPrimaryItem(ViewGroup container, int position, Object object) { + setPrimaryItem((View) container, position, object); + } + + /** + * Called when the a change in the shown pages has been completed. At this + * point you must ensure that all of the pages have actually been added or + * removed from the container as appropriate. + * @param container The containing View which is displaying this adapter's + * page views. + */ + public void finishUpdate(ViewGroup container) { + finishUpdate((View) container); + } + + /** + * Called when a change in the shown pages is going to start being made. + * @param container The containing View which is displaying this adapter's + * page views. + * + * @deprecated Use {@link #startUpdate(ViewGroup)} + */ + public void startUpdate(View container) { + } + + /** + * Create the page for the given position. The adapter is responsible + * for adding the view to the container given here, although it only + * must ensure this is done by the time it returns from + * {@link #finishUpdate(ViewGroup)}. + * + * @param container The containing View in which the page will be shown. + * @param position The page position to be instantiated. + * @return Returns an Object representing the new page. This does not + * need to be a View, but can be some other container of the page. + * + * @deprecated Use {@link #instantiateItem(ViewGroup, int)} + */ + public Object instantiateItem(View container, int position) { + throw new UnsupportedOperationException( + "Required method instantiateItem was not overridden"); + } + + /** + * Remove a page for the given position. The adapter is responsible + * for removing the view from its container, although it only must ensure + * this is done by the time it returns from {@link #finishUpdate(View)}. + * + * @param container The containing View from which the page will be removed. + * @param position The page position to be removed. + * @param object The same object that was returned by + * {@link #instantiateItem(View, int)}. + * + * @deprecated Use {@link #destroyItem(ViewGroup, int, Object)} + */ + public void destroyItem(View container, int position, Object object) { + throw new UnsupportedOperationException("Required method destroyItem was not overridden"); + } + + /** + * Called to inform the adapter of which item is currently considered to + * be the "primary", that is the one show to the user as the current page. + * + * @param container The containing View from which the page will be removed. + * @param position The page position that is now the primary. + * @param object The same object that was returned by + * {@link #instantiateItem(View, int)}. + * + * @deprecated Use {@link #setPrimaryItem(ViewGroup, int, Object)} + */ + public void setPrimaryItem(View container, int position, Object object) { + } + + /** + * Called when the a change in the shown pages has been completed. At this + * point you must ensure that all of the pages have actually been added or + * removed from the container as appropriate. + * @param container The containing View which is displaying this adapter's + * page views. + * + * @deprecated Use {@link #setPrimaryItem(ViewGroup, int, Object)} + */ + public void finishUpdate(View container) { + } + + /** + * Determines whether a page View is associated with a specific key object + * as returned by {@link #instantiateItem(ViewGroup, int)}. This method is + * required for a PagerAdapter to function properly. + * + * @param view Page View to check for association with object + * @param object Object to check for association with view + * @return true if view is associated with the key object object + */ + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + /** + * Save any instance state associated with this adapter and its pages that should be + * restored if the current UI state needs to be reconstructed. + * + * @return Saved state for this adapter + */ + public Parcelable saveState() { + return null; + } + + /** + * Restore any instance state associated with this adapter and its pages + * that was previously saved by {@link #saveState()}. + * + * @param state State previously saved by a call to {@link #saveState()} + * @param loader A ClassLoader that should be used to instantiate any restored objects + */ + public void restoreState(Parcelable state, ClassLoader loader) { + } + + /** + * Called when the host view is attempting to determine if an item's position + * has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given + * item has not changed or {@link #POSITION_NONE} if the item is no longer present + * in the adapter. + * + *

The default implementation assumes that items will never + * change position and always returns {@link #POSITION_UNCHANGED}. + * + * @param object Object representing an item, previously returned by a call to + * {@link #instantiateItem(View, int)}. + * @return object's new position index from [0, {@link #getCount()}), + * {@link #POSITION_UNCHANGED} if the object's position has not changed, + * or {@link #POSITION_NONE} if the item is no longer present. + */ + public int getItemPosition(Object object) { + return POSITION_UNCHANGED; + } + + /** + * This method should be called by the application if the data backing this adapter has changed + * and associated views should update. + */ + public void notifyDataSetChanged() { + mObservable.notifyChanged(); + } + + public void registerDataSetObserver(DataSetObserver observer) { + mObservable.registerObserver(observer); + } + + public void unregisterDataSetObserver(DataSetObserver observer) { + mObservable.unregisterObserver(observer); + } + + /** + * This method may be called by the ViewPager to obtain a title string + * to describe the specified page. This method may return null + * indicating no title for this page. The default implementation returns + * null. + * + * @param position The position of the title requested + * @return A title for the requested page + */ + public CharSequence getPageTitle(int position) { + return null; + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/95/e0c8be1d2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/95/e0c8be1d2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..0f9df2ec1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/95/e0c8be1d2ec3001119baa706e9d70c26 @@ -0,0 +1,772 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/96/10888dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/96/10888dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..5461b9c00fd3fc513aa4465682e70e87cca36a6d GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQaYY4jv*T7lQS|h5*V8PD@dJb zGfWV2j%0YY@&Et-(u-Ft=sZxsVYp-gbGr;f^5z}?TUWk$0o2Ff>FVdQ&MBb@07WJt A3jhEB literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/96/2003e8bc4fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/96/2003e8bc4fc3001119baa706e9d70c26 new file mode 100644 index 000000000..2f68248dc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/96/2003e8bc4fc3001119baa706e9d70c26 @@ -0,0 +1,20 @@ + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/96/817b93ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/96/817b93ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..61dc02527 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/96/817b93ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/96/90657c4f2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/96/90657c4f2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..f1718caf7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/96/90657c4f2ec3001119baa706e9d70c26 @@ -0,0 +1,715 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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 { + return new ActionBarSherlockCompat(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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/97/a1c993ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/97/a1c993ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..4c7b5d459 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/97/a1c993ff24c3001119baa706e9d70c26 @@ -0,0 +1,43 @@ + + + + + + + + 320dp + + + false + + + true + + + false + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/98/30a5542352c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/98/30a5542352c3001119baa706e9d70c26 new file mode 100644 index 000000000..f3eeef387 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/98/30a5542352c3001119baa706e9d70c26 @@ -0,0 +1,89 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.ViewGroup; + +import com.slidingmenu.lib.R; + +/** + * A base activity that defers common functionality across app activities to an {@link + * ActionBarHelper}. + * + * NOTE: dynamically marking menu items as invisible/visible is not currently supported. + * + * NOTE: this may used with the Android Compatibility Package by extending + * android.support.v4.app.FragmentActivity instead of {@link Activity}. + */ +public abstract class ActionBarActivity extends Activity { + + protected ActionBarHelper mActionBarHelper; + + /** + * Returns the {@link ActionBarHelper} for this activity. + */ + protected ActionBarHelper getActionBarHelper() { + return mActionBarHelper; + } + + /**{@inheritDoc}*/ + @Override + public MenuInflater getMenuInflater() { + return mActionBarHelper.getMenuInflater(super.getMenuInflater()); + } + + /**{@inheritDoc}*/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ViewGroup actionbar = (ViewGroup) getLayoutInflater().inflate(R.layout.actionbar_compat, null); + mActionBarHelper = new ActionBarHelper(this, actionbar); + mActionBarHelper.onCreate(savedInstanceState); + } + + /**{@inheritDoc}*/ + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mActionBarHelper.onPostCreate(savedInstanceState); + } + + /** + * Base action bar-aware implementation for + * {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * Note: marking menu items as invisible/visible is not currently supported. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + boolean retValue = false; + retValue |= mActionBarHelper.onCreateOptionsMenu(menu); + retValue |= super.onCreateOptionsMenu(menu); + return retValue; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + mActionBarHelper.onTitleChanged(title, color); + super.onTitleChanged(title, color); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/002bb3562ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/002bb3562ec3001119baa706e9d70c26 new file mode 100644 index 000000000..46a00999a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/002bb3562ec3001119baa706e9d70c26 @@ -0,0 +1,703 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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()); + + return new ActionBarSherlockCompat(activity, flags); + } + + + /** 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/99/1089edc6f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/1089edc6f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..7df0bb7a6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/1089edc6f9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingFragmentActivity; + +public class ExampleActivity extends SlidingFragmentActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/108c455540c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/108c455540c3001119baa706e9d70c26 new file mode 100644 index 000000000..9938728a2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/108c455540c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + View blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/53b38bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/53b38bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..5654cd69429fd0a3502a05b5f827bffab89cc7e0 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr5^nE{-7*QD_LZ%D`aoRl?HIGCc%n7=x#)pUXO@geCyJM=ZAh literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/9018d253f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/9018d253f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..1d47f8718 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/9018d253f6c500111689feaa37e8ab14 @@ -0,0 +1,201 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + public void setBehindContent(View v, android.view.ViewGroup.LayoutParams p) { + // TODO Auto-generated method stub + + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/c06a7fed0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/c06a7fed0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..74831a79e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/c06a7fed0cc3001119baa706e9d70c26 @@ -0,0 +1,318 @@ +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. + mActivity.startActionMode(wrapped); + + 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); + } + } + + 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(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/c09f2a102bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/c09f2a102bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..cc6241846 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/c09f2a102bc500111b2a8b7f47e59881 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/99/f024649ef8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/99/f024649ef8c500111689feaa37e8ab14 new file mode 100644 index 000000000..7d6fe3af3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/99/f024649ef8c500111689feaa37e8ab14 @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9a/400a60aef3c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/9a/400a60aef3c500111689feaa37e8ab14 new file mode 100644 index 000000000..89234d63e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9a/400a60aef3c500111689feaa37e8ab14 @@ -0,0 +1,1185 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/9a/4044c7f125c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9a/4044c7f125c3001119baa706e9d70c26 new file mode 100644 index 000000000..9e664c8ee --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9a/4044c7f125c3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/9b/12178bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/12178bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..5818666d4e64b93da73bc3d6dc2764bcb500359c GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SB0OCjLn02py|R(>fCCT9!M7)Q zv literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9b/203b390e2ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/203b390e2ac3001119baa706e9d70c26 new file mode 100644 index 000000000..4c0b2a16c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/203b390e2ac3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Window; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9b/232090ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/232090ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..719b9234df6fefc32c628a212141681df3414d85 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETB2O2`kc@k8Z(Za)puoZEAojv! z?q20mzFS+?F-&~oGw)ovvN+_p>pJvXn6S<7W@Fox#)9&t;ucLK6T;ku_WZ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9b/40ec4cc82bc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/40ec4cc82bc3001119baa706e9d70c26 new file mode 100644 index 000000000..5cbe7835c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/40ec4cc82bc3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9b/b07c0ee491c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/b07c0ee491c500111b2a8b7f47e59881 new file mode 100644 index 000000000..717e47cb2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9b/b07c0ee491c500111b2a8b7f47e59881 @@ -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.ActionBarSherlockCompat; +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.ActionBar.OnNavigationListener; +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.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; + + 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(); + 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/.metadata/.plugins/org.eclipse.core.resources/.history/9c/51b38bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/51b38bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..516f5c7399c853d112a31d1e17c8c7f17180f9bd GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr5^nE{-7*QpO1)z4*}Q$iB}R!lH3 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9c/805daa0f0dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/805daa0f0dc3001119baa706e9d70c26 new file mode 100644 index 000000000..6bff1db9d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/805daa0f0dc3001119baa706e9d70c26 @@ -0,0 +1,20 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; + +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9c/9094f77227c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/9094f77227c500111b2a8b7f47e59881 new file mode 100644 index 000000000..70c9e2170 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/9094f77227c500111b2a8b7f47e59881 @@ -0,0 +1,18 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + + public MenuScreen(Context context) { + super(context); + mPrefs = new PreferenceScreen(); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9c/c0a415382ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/c0a415382ec3001119baa706e9d70c26 new file mode 100644 index 000000000..4788a91b2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9c/c0a415382ec3001119baa706e9d70c26 @@ -0,0 +1,714 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/9d/3040e8d714c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9d/3040e8d714c3001119baa706e9d70c26 new file mode 100644 index 000000000..e100847a2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9d/3040e8d714c3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/9d/62bc90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9d/62bc90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..94bb8e140facc51317500f9a499bff8d69b58c46 GIT binary patch literal 1263 zcmV_*O=ntr6ly)F+6SKuL$Ibh*R`iD@HZuVL*4g?IwI7He82<#!*f5M@I8l zCg{Dv1W$Fzcs3L;NE=$Fr<|JzVM3(@hGzPCYq!@lQdyTkKnU`?+fnp z>(F)Gr(qbrUhsW{Sj{jDU%RgR#Q1bO)1&VfVpcE~_XxE*%P(A<($9Xs|I&5c=af=+ z*;f-{87ZZ%>$=bT{r(HnQm8bA3XQA~AEs)?*yZh;9N*-9Z*zQ?kA2|bGg0jssqfwU zcKO)OozI@JYS+8!LtVxH4il#d*hFok`+bf-a|Du|<2hY81WgJ0c^9DK#Tld2{b#@1k#zP2{DlFiSLo%^KOZImV(n zX`7Gx*yrt={JtHd6D=c{0W8{i>`C0>_2LIwn9lr|5e_ce$lo*V5nAgC{+cIh8KJb0 zMu>JH%LwEf8S*}F8p|Y>31kG}DH*|M2GiBSML&ffgp|d`2+g+lsUG1Th=LOrVVL zx{0H8TpaViZ}W!mO>{JdH`1&j=9=Yrqke>kbNRG&@A26oW&&Rp$ppevt3JG-qY?ac zXlpGYUL$VLPM?~P;VjepZ&@PqY{zW}Oq$a{B)>zVPLyVG?ekjx;A zk_r5Fe8myJmI0!n;`vX^%^Jmi!B43!DQ~tRsw5IEN+lB17j|0)fT`%K8KNb`l2~h_ zd}&>v))dPGqD9RNrIM#LO`Y62;mQbjbj7pDnUfjB_HctqW-M7nd@(4lrkc(%%!VCC2?p zbb>IW`N`93fr5^nE{-7*QD_LZ%D`aoRl?HIGCc%n7=x#)pUXO@geCyJM=ZAh literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9e/a0ad00d7f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/9e/a0ad00d7f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..6dcbc6c8f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9e/a0ad00d7f9c500111689feaa37e8ab14 @@ -0,0 +1,40 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9e/e03197db29c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9e/e03197db29c3001119baa706e9d70c26 new file mode 100644 index 000000000..56dbd7350 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9e/e03197db29c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Window; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9f/13178bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/13178bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..564fb34b4308750b6922f320e9e114b080ecd538 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SqC8z3Ln02py}XdO!9jra;!2L@ z<=I|~`ucZlc5hPnsi>TGwM)Is^N?0TPy5{UQpwgqqAoKG5)ZX-3ak0R7;B{1mWZ}( p*lxaUe)ue*Z}vC-G%ee~_}P|!&DqTD7lF1gc)I$ztaD0e0st(KG%NrB literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9f/7021b3484ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/7021b3484ec3001119baa706e9d70c26 new file mode 100644 index 000000000..abb061018 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/7021b3484ec3001119baa706e9d70c26 @@ -0,0 +1,30 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/9f/825d98ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/825d98ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..83e9f0ca9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/825d98ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/9f/c28896ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/c28896ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3869d3290 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/9f/c28896ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/a/116a92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a/116a92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e862cb12154541c150fb2d9bb98872bcff506317 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol;0U|59*B=E^EX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`8Mo-U3d5>t~6?){q5*x2~c-pCBZ5 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + if (decor != null) { + mDecor = decor; + } + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/a/e0f491ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a/e0f491ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..205b66e2cdef686c5ed6369b14e64b38d0182984 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr?*8<0#p>+uXou@pObhHwBu4M$1`kk47*5n0T@ zz}*SLjOHg#uLTN5dAc};So9|U`2XLYnVI=;y-5$#f-D2o4GsT&Tr`prfMCHsr=)`p zy9zZlQWAk&gL|Kjh|gcN+0MxMkn!S`=@A+#%ic(Om>d23|9^ht#EF9It^fc3f1ZP3 Y!dJ=4-o~HPfwnMsy85}Sb4q9e06h#o+yDRo literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a0/11f98fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a0/11f98fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a0d9c1b957ea4a6ce62abd120668610d0cb2bd96 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETEKe85kc@k8FK^^+Fc4rlxca~( z?t=fRa*SINS}wBuewp3mefy2x$=b4i8MC*B`RkorJG1!P69>HDUX#kpcm>9d6MZKb ky7}`x**qcrtNL{AY0h>p*ZiBQ0JN3C)78&qol`;+0O3wK)&Kwi literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a0/f02ff42df6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/a0/f02ff42df6c500111689feaa37e8ab14 new file mode 100644 index 000000000..b3034b083 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a0/f02ff42df6c500111689feaa37e8ab14 @@ -0,0 +1,19 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public void setBehindContent(View v, LayoutParams p); + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + public void toggle(); + + public void showAbove(); + + public void showBehind(); + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a0/f1c88aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a0/f1c88aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0eff695d82911a73874d871f3a7b23b71dd8ab44 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Sl001;Ln02py?l}LfC5j;!{`N< zEvnsL$t-6rWU%$psDGg1|4DLDj`q~RzPqNgR|nl=*Rt6dx_ol~p-I||JQ4;82O1ce y*`SQyBHQ|!3>bf({j~je;Zla%ZD->HG+$+yO5M3zoXrBXjlt8^&t;ucLK6T4R5w)s literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a2/10336a830ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/10336a830ac3001119baa706e9d70c26 new file mode 100644 index 000000000..42d510b0b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/10336a830ac3001119baa706e9d70c26 @@ -0,0 +1,203 @@ +/* + * Copyright 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.slidingmenu.lib.actionbar; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +import java.util.ArrayList; + +/** + * A really dumb implementation of the {@link android.view.Menu} interface, that's only + * useful for our actionbar-compat purposes. See + * com.android.internal.view.menu.MenuBuilder in AOSP for a more complete + * implementation. + */ +public class SimpleMenu implements Menu { + + private Context mContext; + private Resources mResources; + + private ArrayList mItems; + + public SimpleMenu(Context context) { + mContext = context; + mResources = context.getResources(); + mItems = new ArrayList(); + } + + public Context getContext() { + return mContext; + } + + public Resources getResources() { + return mResources; + } + + public MenuItem add(CharSequence title) { + return addInternal(0, 0, title); + } + + public MenuItem add(int titleRes) { + return addInternal(0, 0, mResources.getString(titleRes)); + } + + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + return addInternal(itemId, order, title); + } + + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return addInternal(itemId, order, mResources.getString(titleRes)); + } + + /** + * Adds an item to the menu. The other add methods funnel to this. + */ + private MenuItem addInternal(int itemId, int order, CharSequence title) { + final SimpleMenuItem item = new SimpleMenuItem(this, itemId, order, title); + mItems.add(findInsertIndex(mItems, order), item); + return item; + } + + private static int findInsertIndex(ArrayList items, int order) { + for (int i = items.size() - 1; i >= 0; i--) { + MenuItem item = items.get(i); + if (item.getOrder() <= order) { + return i + 1; + } + } + + return 0; + } + + public int findItemIndex(int id) { + final int size = size(); + + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return i; + } + } + + return -1; + } + + public void removeItem(int itemId) { + removeItemAtInt(findItemIndex(itemId)); + } + + private void removeItemAtInt(int index) { + if ((index < 0) || (index >= mItems.size())) { + return; + } + mItems.remove(index); + } + + public void clear() { + mItems.clear(); + } + + public MenuItem findItem(int id) { + final int size = size(); + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return item; + } + } + + return null; + } + + public int size() { + return mItems.size(); + } + + public MenuItem getItem(int index) { + return mItems.get(index); + } + + // Unsupported operations. + + public SubMenu addSubMenu(CharSequence charSequence) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public int addIntentOptions(int i, int i1, int i2, ComponentName componentName, + Intent[] intents, Intent intent, int i3, MenuItem[] menuItems) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void removeGroup(int i) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupCheckable(int i, boolean b, boolean b1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupVisible(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupEnabled(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean hasVisibleItems() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void close() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performShortcut(int i, KeyEvent keyEvent, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean isShortcutKey(int i, KeyEvent keyEvent) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performIdentifierAction(int i, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setQwertyMode(boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a2/339a97ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/339a97ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..fa3698f3b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/339a97ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/a2/60ecce2f22c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/60ecce2f22c3001119baa706e9d70c26 new file mode 100644 index 000000000..3a91f6812 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a2/60ecce2f22c3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a3/a3058aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a3/a3058aff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..d34e20811 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a3/a3058aff24c3001119baa706e9d70c26 @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a4/42fd8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a4/42fd8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ba704b67e3a25f1fb1b16a261c5a1b25fabd0c0d GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzM^6{Wkch)?uQ+l6B^Vrg + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a4/f06925abf9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/a4/f06925abf9c500111689feaa37e8ab14 new file mode 100644 index 000000000..ad62f2ea3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a4/f06925abf9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingListActivity; + +public class ExampleActivity extends SlidingListActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a4/f2aa8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a4/f2aa8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..fa4d76af93de31de153c6a7d41c05496bb14d2c0 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETcuyC{kc@k8Z*AmdP~c#3C@cDZ z^MXtGfey<_%m2nWx~HUtq@RtOD!V+x#J|ag^QD{sZZM%<(R`m!o+Hzd-iC%RO>bP0l+XkKAqp+G literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a5/70da467615c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/70da467615c3001119baa706e9d70c26 new file mode 100644 index 000000000..ac5939bbc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/70da467615c3001119baa706e9d70c26 @@ -0,0 +1,1028 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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; + + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/a5/8080ed4ef6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/8080ed4ef6c500111689feaa37e8ab14 new file mode 100644 index 000000000..b2fd36e6b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/8080ed4ef6c500111689feaa37e8ab14 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a5/c04c6a0226c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/c04c6a0226c3001119baa706e9d70c26 new file mode 100644 index 000000000..e1a6e2072 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a5/c04c6a0226c3001119baa706e9d70c26 @@ -0,0 +1,770 @@ +package com.actionbarsherlock; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; + +import com.actionbarsherlock.app.ActionBar; +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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/a6/42c197ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a6/42c197ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ce0cb3bca --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a6/42c197ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/a7/b0ef28552ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/a7/b0ef28552ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..bb2bc8c60 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a7/b0ef28552ac500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a7/e0838fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a7/e0838fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..575334699663b221b5a2b3251572a7c7a23ddb4a GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nET98VX=kc@k8Z|>$jV8FrZ@U7ta z-*T0WQ@><>I%v71J%hiqt0P@2{q!E)%~9Ermd_VC*s;IdoBnhS>rHk6>|lcSgpVF9 tjEp}SQ%vGx1w)$%c)I$ztaD0e0sua~GRZ2k--6fDKh_j7$vdNDRPM&S{)7kXkz5y{G4S-j93VSIx$q?aiy348v@j2YQR{ zYjkbp*6IJz1u60jwu+P~k zhD-dAvKgjQO+wolAp&}6-~}rC zB|0W8bQbS_h2zdNM0^XycpN$O;rhF&t5DG*WD^{9Fh0zx*c@Vl;~@@#))s+fJ6@35 zbG&6KW)KrQaFD61ELGq<&sCr#m-fpw$tda~goaQn6%DO!NTMJ?D2rOg)v+`7Q9v@T zd&VuVk;~^>oE|e)=9qh{+ygt*DfDz+*r@$E^d4*|9*|0fBXLI({b(o iudTb parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/a9/30af1c540ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a9/30af1c540ec3001119baa706e9d70c26 new file mode 100644 index 000000000..5173806a6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a9/30af1c540ec3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/a9/c0215a9316c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/a9/c0215a9316c3001119baa706e9d70c26 new file mode 100644 index 000000000..1468f89ea --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/a9/c0215a9316c3001119baa706e9d70c26 @@ -0,0 +1,1150 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + + if (mDecor == null) { + initActionBar(mDecor); + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/aa/40e1d7525dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/aa/40e1d7525dc300111ab8b17b137f3789 new file mode 100644 index 000000000..66e7072b3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/aa/40e1d7525dc300111ab8b17b137f3789 @@ -0,0 +1,205 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ab/202090ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ab/202090ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d36f99fecf223779432fb843b823c04d739f05cb GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETEKe85kc@k8FK-lVFc4sN{Ca;{ zvU;8e%Y`P%GdTtG|K%*$a`xS%JL%8+w?$@ueKP6JEX#C%J{El7iLS?_f2=|R(l=Qo klfOK1u;Z=_t1sHgP`H~Vw5GX>6KE@gr>mdKI;Vst03NU~l>h($ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ab/403eb6a027c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/ab/403eb6a027c500111b2a8b7f47e59881 new file mode 100644 index 000000000..82746e214 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ab/403eb6a027c500111b2a8b7f47e59881 @@ -0,0 +1,19 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + + public MenuScreen(Context context) { + super(context); + Preference p = new Preference(context); + mPrefs = p.getPreferenceManager().createPreferenceScreen(context); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ab/527795ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ab/527795ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..8e1efe8c5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ab/527795ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/ac/304e556d2cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ac/304e556d2cc3001119baa706e9d70c26 new file mode 100644 index 000000000..07b07ce90 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ac/304e556d2cc3001119baa706e9d70c26 @@ -0,0 +1,1183 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/ac/405095ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ac/405095ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..8d0b4c34b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ac/405095ff24c3001119baa706e9d70c26 @@ -0,0 +1,347 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + 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 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() { + if (DEBUG) Log.d(TAG, "[getSupportMenuInflater]"); + + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + if (DEBUG) Log.d(TAG, "[invalidateOptionsMenu]"); + + getSherlock().dispatchInvalidateOptionsMenu(); + } + + protected 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/ad/90135f3f49c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ad/90135f3f49c3001119baa706e9d70c26 new file mode 100644 index 000000000..4c74e6fb5 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ad/90135f3f49c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends Activity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ad/c0155d284ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ad/c0155d284ec3001119baa706e9d70c26 new file mode 100644 index 000000000..7e59b8445 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ad/c0155d284ec3001119baa706e9d70c26 @@ -0,0 +1,5 @@ + +

+ + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ae/212090ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ae/212090ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..5ad475dc3f478734be31bc5763ff494e5f120914 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETR8JSjkc@k8Z!P3yFyvu&IDfHo z*MFzV3!h#&I<8{wJG6*7%`^0A*`zgvpO3}4Jy+2bzzZhGPxw0F1DlG16;n~mnRAu= eo1*Vq{$#i=98+;OAz%&ALIzJ)KbLh*2~7aXVK40f literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/af/f2398dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/af/f2398dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..007a4b239244212339b817f8de9474a4dc34fde0 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%zMd|QAs)xyURua|z<`JK;_L&H z*gyPBj&nSGnTg$nOT)YjBQU;+O3-o%)BNS9GKrK90(RDcPwA0 ir}XBH&6co>lKfV`a~Jh`>I4G~X7F_Nb6Mw<&;$VSc`p(G literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b0/20bac3355dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/20bac3355dc300111ab8b17b137f3789 new file mode 100644 index 000000000..beb689821 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/20bac3355dc300111ab8b17b137f3789 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b0/60662a0d2ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/60662a0d2ec3001119baa706e9d70c26 new file mode 100644 index 000000000..dc3e30c71 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/60662a0d2ec3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/b0/923191ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/923191ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..eda10e6123e1e1383c4617228ec0c96680d60dc7 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn1!PZ!4!jfu$#Gb-B{xqtMx1s*(O%+nLV7IxRdaaX6Iu&3070|zpW ye6d-ZyJWwc+pgOl@x443T>9p%`1p8cx&%YrImy|zOvgZGF?hQAxvX + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b0/d03e94ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/d03e94ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..3312cfa7f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/d03e94ff24c3001119baa706e9d70c26 @@ -0,0 +1,33 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b0/d2eb8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b0/d2eb8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d814d02d31183b8f00f475a05c124004983d9eff GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%PM$7~As)w*fBgS%&%9EC|%_%783w8jlt8^&t;ucLK6TeKPwmj literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b1/300e77481fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/300e77481fc3001119baa706e9d70c26 new file mode 100644 index 000000000..32c21c9d8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/300e77481fc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/b1/604b8eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/604b8eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7c0599e3a6fcce1d9b22e47bfdb63afb1d3d9c02 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqEX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`6eo-U3d5>t~6?){p=$oZ!|i46oEul1LdSjZF4rt@IU_AhE`IYK8I wIB$ByaB<8!;4zVtCm{dd@wVRWcBu>u-xEd5&snyt0Gh?%>FVdQ&MBb@09FhvcK`qY literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b1/7005ba380ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/7005ba380ac3001119baa706e9d70c26 new file mode 100644 index 000000000..d0a6d8128 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/7005ba380ac3001119baa706e9d70c26 @@ -0,0 +1,253 @@ +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 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/.metadata/.plugins/org.eclipse.core.resources/.history/b1/f00258ec26c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/f00258ec26c3001119baa706e9d70c26 new file mode 100644 index 000000000..f5f20d91b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b1/f00258ec26c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b2/10348a342ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/10348a342ec3001119baa706e9d70c26 new file mode 100644 index 000000000..e8cb7de6a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/10348a342ec3001119baa706e9d70c26 @@ -0,0 +1,714 @@ +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.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/b2/43df92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/43df92ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6402f28be --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/43df92ff24c3001119baa706e9d70c26 @@ -0,0 +1,46 @@ + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b2/b0551c03fac500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/b0551c03fac500111689feaa37e8ab14 new file mode 100644 index 000000000..050af7acc --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/b0551c03fac500111689feaa37e8ab14 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b2/c1c48cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b2/c1c48cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..b2293670b7fd0f1d20efadcb85df764eaf8f996c GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%zMd|QAs)xyUNz)8;K0FpacBG8 z{r_dveK(bI?AYL#c;KCB(}&!U`A8#&xt?zrk-}5~0`@Qe;$2#LebW~FOSrGz( zC^_$!`3z&JBN4v9eqoN-u~SOGz!Q7{hn#ummnoEhF2XM#rKQMP8rczXxDxhcvV zjkYwkU*qDKWG)?GaMrk#zq#f=c_!QZm^88uZ$c*gcZ%ciW1C@5TohVz;x!w*GyWvmOMpZp;~H>(1|+_Bjyj z@3Fad{8f6N$#2I?@o;Z4-frLRjY*Aivh^pRcG^29aPlQKPDL{HaYXl1yLT2q6%zLE zciri3T%=t}J-oTtnJjvrHL|2Xcp(g3})hUVMqgSNl(dCCfyTZE0ts`%DZzy1e)bWo@sOhIJI?BN>oO_IZm3RD2+&RA)ewtKgfef`x;NRbp5NxDldGUE z^(#cEXnAdsz}`al%{|;pF8_CuO7;rmVRL@Yb0zAX$CHO&TPN|Z&mXHBSJ|Rlq)>j9 zt`YD|IL+%dZtBx?EHS1S0{b*ohjzBdbj(k*PwikwtX@dN!6>-Po77J<5^{yjsl)O9 zEX|Q?x!foHGf`NVDX{MM`X$wWS`XSy*jb!yJz)Tum3kv}!}&nT*CI)HeDC+xypCr)%#9G)lLf%s)73-jcI*8o6Nis@T)5Q}>zw_%heP zwM`1D5~WbAsYBNc=?KJYK)nyR_jin-vxOx1Tpy@Z^|2Ij_^L z8R2=g9g3^NxXJDJkUdp}sY?;>+w~r#RAG-uRWnEh=l9-}_4e$hCfd5SCBGgP_Eev% z@-tA@J+VD^@1E$=v3FM;ZiIfet<#LV2;b6Nah56^jenVmqYP;H5UKh)zZI@C4EFVs zT{-kAaAFn`W^v0{y~k!?C}y;>l|f7PexHxgtCOENKIG;a>4jRo&bAf-Bm+v3Tz&lO zci{=At?{5im&8$ANZqvNNN2}x;GY7y;hyzN@O6|ns znJJnImvRlQ`!st>Yn4Wy@mG{-QBU_F1)T}uBABKD`9)t}=66*$~*F%1R V)fNE5W|Ds?h%=suyJ>gy5=Q_4 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b4/81288cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b4/81288cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..40d0d1645cbf05e30bf092ace45403281da7f318 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^96&6^!3HF|1ZAax6icy_X9x!n)NrJ90QsB+9+AZi z4BVX{%xHe{^je@`oTrOph{nXLlMZq=7znVWA2oV&$ZSjW?F|h7ziq5jS#e}ezd(V) z{M(JTeF@SBrcbxn{QE=WZYK^04VRD=846z*9&b9ovtVvpnl(eT%D#{N!SzC3^S3#* f<|u1MCr7h0-;i__`(soEw28sf)z4*}Q$iB}%FaDT literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b4/c0358fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b4/c0358fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..587337caf74f9ba3d32ba1c7cc8fb8b0b5ba245b GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^EI`b~!3HEJ|NhSh5-4`^4B-HR8jh3>AfL0qBeIx* zfx8og8O=|gUJDeo^mK6y;h4Gh+(zC53JlB#xw8$}k`45e4cLk;e3y7!_%!uv(Z^d6 t0#9x~Qa^f(Id{#0H&;LIP<)f9-+fKc+F|3Yl|VxnJYD@<);T3K0RZ_tFJ}M% literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b4/c0b1d4870dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b4/c0b1d4870dc3001119baa706e9d70c26 new file mode 100644 index 000000000..60bd3d919 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b4/c0b1d4870dc3001119baa706e9d70c26 @@ -0,0 +1,18 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); +// setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); +// setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b5/00a545fd52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b5/00a545fd52c3001119baa706e9d70c26 new file mode 100644 index 000000000..3261aff6e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b5/00a545fd52c3001119baa706e9d70c26 @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b5/8042022029c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b5/8042022029c3001119baa706e9d70c26 new file mode 100644 index 000000000..b47aaaa98 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b5/8042022029c3001119baa706e9d70c26 @@ -0,0 +1,19 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b5/a1768cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b5/a1768cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f8d619b4d47ab5b104d6b1042c27fb16a3beca47 GIT binary patch literal 523 zcmV+m0`&cfP)C3<00004b3#c}2nYxW zdK`GU$CA-E+tg1FUj3CV1Ez}l7r{NB_YWZ zgb+-Kh;2qAgunr)owSNT9jE|#(}iQ{0=K~F)j_f4%AIwfW*LI4SCjSena$3zhl@?`-N)f>fC&00iU>|7tSL}YGdG832Z z7Ry93w=$W@5~IozqskJa$`YfBUCf~8@-tLEe(Yg7ZJ&$d5^vAJVlkbz&)H#>=1rCU z=lI*@D9QucAy4<)W_$YF0~q6}sI5vC!>ie*fX@E1>5KTAKqegRE>ywO`Fw(I}^ N002ovPDHLkV1grX;W+>R literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b6/00d28fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/00d28fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3c4701fc21a7b70310c0fb65f82c96406bf676c9 GIT binary patch literal 2869 zcmV-53(E9~P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0001BNklg>n)kmH7JfR>L=7gsVyOrjh?O!kd687gq;GddYfQoE z;^b_j0~Z<2SccpV5FkK+00HtJq?RWj0>Wbj0t5&UAQ6yPz9lR;$^ZZW|NjF3iYJRN Tx*zQx00000NkvXXu0mjfH|R+l literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b6/1020ba2b25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/1020ba2b25c3001119baa706e9d70c26 new file mode 100644 index 000000000..b266112c6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/1020ba2b25c3001119baa706e9d70c26 @@ -0,0 +1,1181 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/b6/24af8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/24af8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7c2cbe5356e41d5b7faf4172055d15ef2363a1ac GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%o}Mm_As)w*fBgS%&#cG8BEZxy zm1Nj*Ve@bQV4k86D_j?g^+uUwT?8?B*}4y~%+*Pfh!eYLYABIk`)mHR3W;bIU(qc` aco+`L`*%KR`u!MaD1)b~pUXO@geCwrnJLNu literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b6/80379b1b2cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/80379b1b2cc3001119baa706e9d70c26 new file mode 100644 index 000000000..cacbb4625 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/80379b1b2cc3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0058aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0058aff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6d4814f86 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0058aff24c3001119baa706e9d70c26 @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0e3b66df4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0e3b66df4c500111689feaa37e8ab14 new file mode 100644 index 000000000..592bfb760 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b6/a0e3b66df4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +// setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); +// getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); +// getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b7/c18896ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b7/c18896ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7d45e81be --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b7/c18896ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/b7/e2128dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b7/e2128dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..8f10bd5222239e82e49c5120888fc9a07a324b42 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|M^6{W5R22vKmPx>XSQNv;&5z| z@wwFK#IyY<~E UNZ9H+7ibuRr>mdKI;Vst0LZr`*8l(j literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b8/90aa1d6f0ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b8/90aa1d6f0ac3001119baa706e9d70c26 new file mode 100644 index 000000000..6d9c4843a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b8/90aa1d6f0ac3001119baa706e9d70c26 @@ -0,0 +1,350 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.ActionBarSherlockCompat; +import com.actionbarsherlock.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); + 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 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() { + 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/b8/f0543b872ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b8/f0543b872ec3001119baa706e9d70c26 new file mode 100644 index 000000000..f2b8307db --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b8/f0543b872ec3001119baa706e9d70c26 @@ -0,0 +1,350 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +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.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.ActionBarSherlockCompat; +import com.actionbarsherlock.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockFragmentActivity extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + 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; + private Boolean mOverrideNativeCreate = null; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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() { + 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 (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : 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 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 + /////////////////////////////////////////////////////////////////////////// + + @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); + + //Dispatch to parent panel creation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule"); + mOverrideNativeCreate = result; + boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu)); + mOverrideNativeCreate = null; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + result |= menu.hasVisibleItems(); + } else { + result |= fragResult; + } + + return result; + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @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); + + //Dispatch to parent panel preparation for fragment dispatching + if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule"); + super.onPreparePanel(featureId, view, new MenuMule(menu)); + + return result; + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @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; + } + + //Dispatch to parent panel selection for fragment dispatching + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule"); + return super.onMenuItemSelected(featureId, new MenuItemMule(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/.metadata/.plugins/org.eclipse.core.resources/.history/b8/f3c88aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b8/f3c88aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..b0dc31fb3dd17668dbd8e3158b290544a50eca15 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{< mCats; + + public MenuScreen(Context context) { + super(context); + Preference p = new Preference(context); + mPrefs = p.getPreferenceManager().createPreferenceScreen(context); + } + + public void addCategory(String title) { + + } + + public void addItem(String title, String cat) { + + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b9/914f8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b9/914f8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d281adb553af892f758407b846bf31810b9d776b GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^%0O(y!3HF+1t+BgDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?Tb?eCArY-_Z*Jr|WFXM+FkX}IYP%rckLbO*zpbz{y7bYSIrPClD)2Hc3qcaC*%7oYhKR%+5DyWbJ~oU4#{OKNlluqE0VJm zR?Ud&kaA;Q)O4{aB-unUR3g{I@EB82%f_aZWF5r`AFqi`v@HN~5*v&Qo>cRA$gv99 zHaapFv&*%1#4~?bwda`9)~}vNKHF@K`t|cGZ}Xb{RR4x!PC{xWt~$(69DLj BcXj{( literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e06a3a3c10c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e06a3a3c10c3001119baa706e9d70c26 new file mode 100644 index 000000000..8dfcf5151 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e06a3a3c10c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e2d696ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e2d696ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ac25c3736 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/b9/e2d696ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/ba/2002f03b15c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ba/2002f03b15c3001119baa706e9d70c26 new file mode 100644 index 000000000..0aa0efaeb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ba/2002f03b15c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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; + + public final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/ba/931396ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ba/931396ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7b830b9c0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ba/931396ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/bb/20af8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bb/20af8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..85d7aadd4dfb619883f68f1cc63e629698b5dab5 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQbwLGjv*T7lQS|h5*V8PD@dJT z6Fe3@|6GeFPb#ATqtK84|Mweqan0i3X%}$jvMQLwz#trO`SaWQ^{znO44$rjF6*2U FngE5o9^U`} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bb/20d7532a16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bb/20d7532a16c3001119baa706e9d70c26 new file mode 100644 index 000000000..d5266c885 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bb/20d7532a16c3001119baa706e9d70c26 @@ -0,0 +1,1154 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/bb/52248eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bb/52248eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3bf8e03623c94b68d31963ffe7e59c72c3dcc059 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqEX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`86o-U3d5>t~CW>mH@a{g&g;s7!l1y4Byva-KaJLVIiI)OpBYodjS ofJx&-C1HsL_x|*Yp0_#7zz}{&aC*>dO_0?Lp00i_>zopr00f~Zw*UYD literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bc/10f98fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/10f98fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d0df29d8b3fef9f71cda9b7a0975c68dcfb05685 GIT binary patch literal 290 zcmV+-0p0$IP)(^RAa&-b-qmfdL= zKY^DZ_=R_1v^+>Y{!mW=MF!v|2#Q>Q>z_&4i6T94j-Y4q`P>I~g?cE`S~^QhBCU5$ z-8a`dJ38hrt)qwm8XJx0+%VAuW=z7Jg@`1pBAUrf#Ef=wZl|UqH7RO)u1OwK(@xK~ zuV&5*5lN0GQV~igR!o15*n1TfDTP6ilQ72>QBJOyK^2jQYHlAzlrUMuFCtAA$s$=K oi)4{qME3aCu~lSF#Q4a(0o}otDK%H_Q2+n{07*qoM6N<$f*T@rc>n+a literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bc/705493ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/705493ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..58bafaf1e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/705493ff24c3001119baa706e9d70c26 @@ -0,0 +1,36 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bc/903191ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/903191ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..45a0f1da0d01b7c0ba53830285c67d629bd0774a GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU~2MoaSW-r^>)^McjrWjeSoS8SCOEBs|%|?VJ7D=T9Yz_dLJ8 zJ9zK=&-=vhubx}{vF6<8-!m`2Et8%6G=f2_fi-~)r;kY>>MAgRkm@i7CT&PKJ^T(I*&Av>d6O5U0r~;hkX|;LrY6t%e!5sze0;lgN zzhmA1v9d1mdTWRDgJXqP4j5dhQr@DSSRpJN-*(9Bjp4$N@%tt%vt{r<#9TCmVT&q5 zPY_dpf5x8W&TrHi1EzgwuzL61gP~v}`*h7_ev9YX^%66WzmeOz)Rwd1sPzfWyZX+; ziqW^(w(Z~haJj|{8OsISSA~|G@%CQ8Y_d#7=yl$KAFm&t%#H|W$kcQ2;yBguIO76W zkG?He)AQ@KipLqRU6Nb%FPk$;xS@jW=|$x{C80dl?QT)`*~FQi^@N=fie6YGbN2D| z=`W4NG-chmgqp9bsxquQQuyVroI59@gwb7QnV5NMi~&p85J-Uv+l!N+#T%5W;<7yr4}f9Ow$JGA?da_{7}kE@t}@ET5LG{B2CIDTQC8`Twj U_qmZcFi|piy85}Sb4q9e0Mf@O?f?J) literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bc/e002f968f3c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/e002f968f3c500111689feaa37e8ab14 new file mode 100644 index 000000000..77e9781c3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bc/e002f968f3c500111689feaa37e8ab14 @@ -0,0 +1,1181 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/bd/308e08963dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/308e08963dc3001119baa706e9d70c26 new file mode 100644 index 000000000..b47aaaa98 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/308e08963dc3001119baa706e9d70c26 @@ -0,0 +1,19 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bd/804a8bb591c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/804a8bb591c500111b2a8b7f47e59881 new file mode 100644 index 000000000..ab3121e89 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/804a8bb591c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bd/81ec95ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/81ec95ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ab76fa7f6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bd/81ec95ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/be/00b9f6452cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/be/00b9f6452cc3001119baa706e9d70c26 new file mode 100644 index 000000000..c4f58f695 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/be/00b9f6452cc3001119baa706e9d70c26 @@ -0,0 +1,1183 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/be/21af8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/be/21af8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f7b01e012f895bfe2c4241e1d48771fc372b35cb GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQU;zbjv*T7lQS|h5*V8PD@dJT z6Fe3@|6GeFPb#ATqY%TTAPubyB?B2J9?cgAJee4pt{u!zH{AaisF%Uh)z4*}Q$iB} D0X-aq literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/be/a04a6a8e0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/be/a04a6a8e0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..83114c3aa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/be/a04a6a8e0cc3001119baa706e9d70c26 @@ -0,0 +1,253 @@ +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 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/.metadata/.plugins/org.eclipse.core.resources/.history/bf/7021a05c25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/7021a05c25c3001119baa706e9d70c26 new file mode 100644 index 000000000..032a9f68a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/7021a05c25c3001119baa706e9d70c26 @@ -0,0 +1,1179 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/bf/807c6b3949c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/807c6b3949c3001119baa706e9d70c26 new file mode 100644 index 000000000..3fbcc4c98 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/807c6b3949c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends Activity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); +// ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); +// getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bf/9021e1b05bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/9021e1b05bc300111ab8b17b137f3789 new file mode 100644 index 000000000..ae993f592 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/9021e1b05bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bf/90b3badcf8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/90b3badcf8c500111689feaa37e8ab14 new file mode 100644 index 000000000..962a0a5e9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/90b3badcf8c500111689feaa37e8ab14 @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/bf/e0d01f1995c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/e0d01f1995c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2c30d9022 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/bf/e0d01f1995c500111b2a8b7f47e59881 @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/102a1f3c26c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/102a1f3c26c500111b2a8b7f47e59881 new file mode 100644 index 000000000..5c0e635b2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/102a1f3c26c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib; + +import android.preference.PreferenceScreen; + +public class MenuScreen extends PreferenceScreen { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/4023f514f3c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/4023f514f3c500111689feaa37e8ab14 new file mode 100644 index 000000000..88db11879 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/4023f514f3c500111689feaa37e8ab14 @@ -0,0 +1,1025 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.FragmentTransaction; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + mActivity = activity; + 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) { + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/c0/40afb916f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/40afb916f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..7b985d007 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/40afb916f6c500111689feaa37e8ab14 @@ -0,0 +1,18 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + public void toggle(); + + public void showAbove(); + + public void showBehind(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/411b89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/411b89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..263542f03 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/411b89ff24c3001119baa706e9d70c26 @@ -0,0 +1,186 @@ + + + + 4.0.0 + + com.actionbarsherlock + library + ActionBarSherlock + apklib + + + com.actionbarsherlock + parent + 4.0.1 + ../pom.xml + + + + + com.google.android + android + provided + + + com.google.android + support-v4 + + + + com.pivotallabs + robolectric + test + + + junit + junit + test + + + + + src + test + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + true + + + + 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.1,) + + replace + + + + + + + + + + + + + + + + + release + + + performRelease + true + + + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + ${android-maven.version} + + + true + + + + + manifestUpdate + process-resources + + manifest-update + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/71728eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/71728eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..42cb6463e4c28c6aeffa315c4fc869867dbb6b7c GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^{6MVD!3HFkzrK_Oq*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMg@oJyIHz9Y|%SiynA|kd)58s-{92FmHki*;@KxND!%;H%=F4ZU(n;yg$GVRgBd(s L{an^LB{Ts54)-;@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/9040293052c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/9040293052c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7d0b8720c2d694e4886f59550d9168fd02858ddb GIT binary patch literal 1501 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVi$$*u})q(AB`v%-Gf0&DGr0z}(Q# z($pEI*Cju>G&eP`1g19yq1ObbUQklVEdbi=l3J8mmYU*Ll%J~r_Oewb7PnZKxf;5< z8k^xX52`l>w_A*G>eUB2MjsThND&Pa0;V1i6P|2=9C*S{%>$^X_i1JA2%={9WZc%kQ=Gi;qqBQR6jt zpZM_82bKyZ8%DkUM?UO->h{N8U&AcCfN@HbgazC7m249|RO%VcT=i#o@6J=_Y@To~ zc!k)R*>|=Ga$O8N&~WIhTZ!0(6&IGpr8Dl&^IQDrT$tvT>a9AxQ6g6pxJtCQ@xNAD z(6n=3{H|lR6%36$%KO>#=7Q_X3&(nk?9x{YzfVw}{wKD>DQtN`-JO%?q60gH z+YTqHJ@9?_XH^VO#6p%gT65x=ryW={<^NW}4>Mek%nONi6^v#yUJx{0C&gfScaZ&= zrZ7K$;b-5KZXGmPeo0_@?;@u8Vvi(0rrwf1n;3Zi@GXUCPD8Kf|Nkm37yByyfa}Y} zGn|Ut2?B2#tTR*1xS}F%el{u&>uZpCWGUgj`SSKRYi7>9_y0Y|jjc+;aT(G&m(wJ^ z_@rG^S@3vWO9h|VL9JZ(Z5PVIA5As8eRa3cwlB*kFfHQBO|s&)2)!X~btSUFpglTf zXX>jzTl0Q9y(~PoQY67qn^FIP$EVOJZjat0yY#rFjvs#h_u^YlNc8?ZGM|B&!Q)*O Uhr^zq&Y%L<)78&qol`;+0PCJIBLDyZ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c0/a15891ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c0/a15891ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..65061c0f45e63fe0fea0bfad9c71ee52c07ef38e GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=q&!_5LpZJ{Cp0wt58!$3;rOwB g4O4-x!vO{c$tv!+&aYQD0#z}1y85}Sb4q9e02-9s&XV^0^y5RRG22KRnVX>4qKXwM^^Uwi5RN2-aD!@msM(PItY>s_{MVWOZ(=mjBT1_sGr W&p6(H%v1uJ#^CAd=d#Wzp$P!PC@9VV literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c1/425095ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c1/425095ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..4f6891e1b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c1/425095ff24c3001119baa706e9d70c26 @@ -0,0 +1,72 @@ +package com.actionbarsherlock.app; + +import static com.actionbarsherlock.app.SherlockFragmentActivity.DEBUG; +import android.app.Activity; +import android.support.v4.app.ListFragment; +import android.util.Log; +import com.actionbarsherlock.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public class SherlockListFragment extends ListFragment { + private static final String TAG = "SherlockListFragment"; + + private SherlockFragmentActivity mActivity; + + public SherlockFragmentActivity getSherlockActivity() { + return mActivity; + } + + @Override + public void onAttach(Activity activity) { + if (!(activity instanceof SherlockFragmentActivity)) { + throw new IllegalStateException(TAG + " must be attached to a SherlockFragmentActivity."); + } + mActivity = (SherlockFragmentActivity)activity; + + super.onAttach(activity); + } + + @Override + public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { + if (DEBUG) Log.d(TAG, "[onCreateOptionsMenu] menu: " + menu + ", inflater: " + inflater); + + if (menu instanceof MenuMule) { + onCreateOptionsMenu(((MenuMule)menu).unwrap(), mActivity.getSupportMenuInflater()); + } + } + + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //Nothing to see here. + } + + @Override + public final void onPrepareOptionsMenu(android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[onPrepareOptionsMenu] menu: " + menu); + + if (menu instanceof MenuMule) { + onPrepareOptionsMenu(((MenuMule)menu).unwrap()); + } + } + + public void onPrepareOptionsMenu(Menu menu) { + //Nothing to see here. + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + if (DEBUG) Log.d(TAG, "[onOptionsItemSelected] item: " + item); + + if (item instanceof MenuItemMule) { + return onOptionsItemSelected(((MenuItemMule)item).unwrap()); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + //Nothing to see here. + return false; + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c1/7013a1ff4dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c1/7013a1ff4dc3001119baa706e9d70c26 new file mode 100644 index 000000000..4a518d2de --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c1/7013a1ff4dc3001119baa706e9d70c26 @@ -0,0 +1,209 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c1/c057563952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c1/c057563952c3001119baa706e9d70c26 new file mode 100755 index 0000000000000000000000000000000000000000..45d2398ae7521691201fb3ff1353696368ea610a GIT binary patch literal 1429 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsViy+1SF^#l_Lp*u})q(AB`v%-Gf0&DGr0z}(Q# z($pEI*Cju>G&eP`1g19yq1OqgUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZns$AG!Lpb z1-Dx)aq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@i4sr68VPIh5^mK6yskrs# z`gw1WM496sXC{{NPkqvVcb7`il8LD-*(IG;DjFpdY@bFRxnRG<-eHyZ+}8>n8(gnA zvhYXey5!miybkCLQEST3(%!vK{s)iF>Abfa`ggN`ZxnxhPUn10+C2ID7tcN|^3$FD z{K}52%vWq2R@^ukp%eC|K;2KdNvAHE)Be=n2(77F`VNk-4+!YJs&<>-d*iV88I1{Z z)hArnOLnQZKWzQy;sw`>?b#OX)m2K@m`W0P>(<1X54|$|0QKJVVq z_de=SSeB#HWUY0(?_6LpUA-jqaB|t9OrA%p`eshxp0V1bVR6>JA0m=OQX$I;pg#+Ir{`FS4~*Br&n{ez~8GJ33}fm zCY#3yBt-~+IdGrzY=Esvemtw9Pv!oAlQJBawuv69Uwmqn$JuaghdPe^R(8j4XR&>7 qwz*(1{f_M2U;o?M?GEf?U}iX+R4yX8#r6ZJp!9V0b6Mw<&;$TvzYxd( literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c2/10bda06a4ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c2/10bda06a4ec3001119baa706e9d70c26 new file mode 100644 index 000000000..8b8108b45 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c2/10bda06a4ec3001119baa706e9d70c26 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c2/a3e78eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c2/a3e78eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..09a2992ccaef67bc924ba4b3364b2c7c05920cce GIT binary patch literal 417 zcmV;S0bc%zP)KmrqN>Fc^oQq;b>Mt0(a$ z!tgX@A7RK4{kGy^A3#w21maN-UfpV|U0)B)Mu)Zk(%$xiP)OBD#retJ&sicWsshEL!WHUI0Z}S=i2Rqw=-{<_oUlU4$I1(Vt^KG}@Sd2k4!kUV zp9d;G14UN$xn@Z2Tv!X1WCiPlZi?T5Wo`s>dMMw4?2=HB&MqLoAdzh3Gg0e200000 LNkvXXu0mjf#CNP@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c3/106dde3c52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c3/106dde3c52c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6ce93766cb923d33ae0d0564bf15e2baf4b8da32 GIT binary patch literal 2582 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 e9{yAVQG(#6NIN$4t6Y))sd4nJ zaCd?*qxs3xYk`99o-U3d5>wYsbmTgqz{8?`Dg4L(`abqnuZs;wTVv8ZBg|GX^f4xE z5ck=nld$UVv7H|oR+P30etdkz&;0SSW2^3}yn7y4rozh{Dy3k((DE(NNCr<=KbLh* G2~7afj5MhL literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c3/80b442fd23c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/c3/80b442fd23c500111b2a8b7f47e59881 new file mode 100644 index 000000000..08daa7100 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c3/80b442fd23c500111b2a8b7f47e59881 @@ -0,0 +1,205 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c3/93de89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c3/93de89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..321f07c8b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c3/93de89ff24c3001119baa706e9d70c26 @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c4/70208f3228c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/c4/70208f3228c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2f7547225 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c4/70208f3228c500111b2a8b7f47e59881 @@ -0,0 +1,35 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c5/233e8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c5/233e8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..897a1c11a06923f0ee630a3ec44b40118c1fa4d3 GIT binary patch literal 602 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877l!}s{b%+Ad7K3vkswhI zFm^kcZ3hx8D{xE)(qO#|6+TOsF)%PDdAc};Se)*?;+-wxD8l++z18QgepiI9o*=R4AA9|r|3}>uTm;M6YILUxmVi!uBjgaN)~;(wEWpmNk!cW z(d%Z<{E>P~YK!lT=8FgRsYuTJwQ$0$u+I~@?rdLb^6_f+5jpHV#tRQqPS1ijb30F2_W#pYUFO#_XV=?h zOHP?#2^DqDa literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c5/c08896ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c5/c08896ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0a87bd3f7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c5/c08896ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/c5/d049ec4e4ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c5/d049ec4e4ac3001119baa706e9d70c26 new file mode 100644 index 000000000..c7803d78f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c5/d049ec4e4ac3001119baa706e9d70c26 @@ -0,0 +1,30 @@ + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c6/70c1ac002ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c6/70c1ac002ac3001119baa706e9d70c26 new file mode 100644 index 000000000..b02773575 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c6/70c1ac002ac3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/c6/733698ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c6/733698ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..397fd1c2d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c6/733698ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/c6/c1358fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c6/c1358fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..155c4fc753ed43185b31df3bea2af1ea5b3e7482 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^EI`b~!3HEJ|NhSh5-4`^4B-HR8jh3>AfL0qBeIx* zfx8og8O=|gUJDeo@N{tu;h33haPQZY#>U2n_RP$O>mRT6my}r84nJ zaCd?*qxs3xYk`6eo-U3d5>t~6?){p=$oZ!|i46oEul1LdSlBa@C*nY4{!0_J9HA2p woHspUxHx7V@R-QS6OjM!cw6swyHo~-e~lvMp^1B@1I=RaboFyt=akR{0Ay(_r~m)} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c7/d3cd91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c7/d3cd91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c6c3f1ec248835c16ee8a8f9d253769ea4196468 GIT binary patch literal 1309 zcmV+&1>*XNP)>2T29Hys?P&Vm zZA9*OOSNlf`Pu!y*8AUEO|D+e=9Pi3BR)agfw#}SukU>S5_JQH{fFX7qt#y26-7>F z^lg#%AL~){ay($Vl%dNK|ns=8F95J5u4IuT)_iO}FO5AO!x2YA-ev{((MiCMb95Z27y1N{d~<$0ZOiAzT-4$^Y~d8=D&GctVLiOE-HZCX=>916 zaB}eD93BUF6!cN|FY@&i`W7!}IIL?H*U-;b(9ZeC>T4fo-D~%;%Al$SM;o1{CK^c@ zLsL?U%;F5uW`mKV6p@jG8Wm~81rvcAg~E0r38^#=q@={j6{7*N{-mRal zZyi757l1u@+(UUVUpKQfbx4*^AEZ`NBGTk&djR!;W=;+8vR!2ZvkZUiF_Uw;@^@UHY_tFNo|bZ|HqK}~Z_0kB z>1@!nFOf~^{KOi&lvG5Os4i`3m5LaZ>S{(}C2cS_3u25qx+GSC0x^F*mC<6C%zjX} z`(@Gi@=yT|C0D;bu>bAn+W30Hh5ZfH4VVpRc=$wP71`a_ciV~TTQkNXRQHQat7toU zZx*3Z?Q~QYQO|ZUR_Tl#qXtzIiPWWo(#}&aV(i6KuEST$lYVRUVscgaEz?@VCh+@z zYdAdahv=OS&fP(?9$16?`l0%F3gfnP`B71?hw4@2e4pjZouU=>X|R*`N-YD-DJj}uU$#5 zV>X}RzD~bXHhFf?KK=4JTCWrMiS*`U`G2n9l*Y@cp7B$uQwuKJNIF$ 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public void setContent(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(); + } + + public void setContent(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/c8/93c08eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c8/93c08eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4ce73edce72e648c51fb85318d1371bc9770b000 GIT binary patch literal 1165 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfizez!?|}o;S3DSQ$1ZALn02poqj%F+EwJZz47L_+nuuJ2Q4z2 zqm&e*0$DQx4sTqg^!0$`s-g$|4;qflZ*ckFD7Ts`bZ>!UK%rs{7HZyAaH@aKEfTQc z(CR%$S?96abl05G-F(|Si_LUV;?$6kux)>%v=)2DUfpwT%PQ8|6^&m$u}%%W*3rdf zl`oQNvN&>WhAa0khnps!G6EK_TCpZ6=uP_{^)H>%wyt5X^53?*IxN|0o#E77R`PdD zm%Wa|cNB9$z_AP5mH=4J^LP6!o!<(RyDvF+#7%B*F3D>^@) zG3au=^KjWsn^#jyew;NrnOPLU6Z$MNVeT*c)9TLijM8T&&Ec75wYjFybd#W68%QTW}f06Axoa$IU9~?Nqc5iru{em z%^e?{s+j1J=mX5HswJ)wB`Jv|saDBFsX&Us$iUE0*T7QO&@#l()XLb*%EUs~z}(8f zfYD-4D2j&M{FKbJO57R>QdwRCHAsSN2+mI{DNig)WpGT%PfAtr%uP&B4N6T+sVqF1 RY6Dcn;OXk;vd$@?2>^cl_{IPL literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c9/314790ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/314790ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..7ef2db75e273c3a4fa34a867d43714d47b67dfd9 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#v+DHBf@#}JFt$r%|L2@FmD6{OlE zCs-P=E^ay;FECBu-~a#X*$!!Fy;QT1l2!H>nDyu1;UEQuS2t(=%(&d{0o2dn>FVdQ I&MBb@0Ph$gIRF3v literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c9/40fd8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/40fd8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..a17b6a78920848c37a67246a76749b4cc1425a15 GIT binary patch literal 566 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE&~Ijou`Xqh{y4_R~-EgIfxwlm><>K$vu5h!wc4! z9iP>XtrZVs65@3e-rKIN%Hh(x{ewWxt1j(s|L*kJ zSoUnickXv5=i7?TNH`^EJfpg4#&4;Y0qR0+drTg2JXGfUq3}Rr;{P9f_n*&gD7KkW z&D4IqLivGGRq&kmAH6(eA0`F~7S8rex88HAVS=03cY~80?cpzkFa4S5A6;t}xJ7Q# z9-saRVPfVT##U33AAO3A+Ypl|_94?@cK)tT4*8AF;-^j1iVm!a-M-<=iX&Itr@TnW zJpXO;4EOj9!Ar}#BHVL6_dHGGELXBQqN>Q8)gj~`k@s=>rw|ur?|x;upO5s^{asBY zKb@S=&SWDRsQzHyR;N3i0@8Cfnf~0l`P3PA4VeH(Ut{H!I{}l<<aB zB5gMTgH*M|HKHUXu_VC#5QQ<|d}62BjvZR2H60 RwE-$(@O1TaS?83{1OW6u*u?+< literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c9/416e90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/416e90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3c909b51306d684dc9fc4deb674ab1e1feb7004e GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#xSIG!$!Ar_~TGcqy~7@GboNVOeo z`FL&lz5>PtO@Rj=>T@VLG&w|ZbqQ*{RI`whRrVK{_2=K=E+vL!&S{*=@1z8QW-xfV L`njxgN@xNAaNr>U literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c9/438c8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/438c8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4ea7afa00e2bfe057472ed5a196080fc80ad7383 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr2)kE{-7*QBRJJkl{&7FVVepxUS$Rt1LT2VAvn7lLLt0oo!v4%( tpjG6n=4tr&fORvYRP%q%M>EqU82;Q9of*be(FHVz!PC{xWt~$(699PnDoy|Z literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/c9/b07438830ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/b07438830ac3001119baa706e9d70c26 new file mode 100644 index 000000000..d514364f6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/c9/b07438830ac3001119baa706e9d70c26 @@ -0,0 +1,145 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + mViewAbove.setCustomViewBehind(mViewBehind); + +// if (mViewAbove == null || mViewBehind == null) { +// throw new IllegalStateException("id slidingmenuabove and slidingmenubehind must" + +// " be declared within a SlidingMenu"); +// } +// +// // register the CustomViewBehind with the CustomViewAbove +// mViewAbove.setCustomViewBehind(mViewBehind); +// +// // now style everything! +// TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); +// // set the above and behind views if defined in xml +// int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); +// if (viewAbove != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewAbove.setContent(inflater.inflate(viewAbove, this), null); +// } +// int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); +// if (viewBehind != -1) { +// LayoutInflater inflater = (LayoutInflater) +// context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// mViewBehind.setContent(inflater.inflate(viewBehind, this)); +// } +// float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); +// setBehindOffset((int) offsetBehind); +// float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); +// mViewBehind.setScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ca/20a5994249c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/20a5994249c3001119baa706e9d70c26 new file mode 100644 index 000000000..c35564961 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/20a5994249c3001119baa706e9d70c26 @@ -0,0 +1,218 @@ +package com.slidingmenu.lib; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View blah = getWindow().getDecorView(); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + View blah = getWindow().getDecorView(); + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ca/90aabe775bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/90aabe775bc300111ab8b17b137f3789 new file mode 100644 index 000000000..5a6860835 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/90aabe775bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_offsetBehind, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_scrollOffsetBehind, 0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveContent(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindContent(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ca/f08c94ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/f08c94ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f2aa64d2d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ca/f08c94ff24c3001119baa706e9d70c26 @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cb/102615a1f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/102615a1f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..eb184cf21 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/102615a1f6c500111689feaa37e8ab14 @@ -0,0 +1,199 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.AdapterView.OnItemClickListener; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; +import com.slidingmenu.lib.app.SlidingActivity.MenuListItem; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuList; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuListAdapter; + +public class SlidingFragmentActivity extends SherlockFragmentActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cb/40c197ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/40c197ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..673ec554f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/40c197ff24c3001119baa706e9d70c26 @@ -0,0 +1,44 @@ +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.TextView; + +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) { + setText(text.toString().toUpperCase(Locale.ROOT)); + } else { + setText(text.toString().toUpperCase()); + } + } else { + setText(text); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cb/9018bc4f2cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/9018bc4f2cc3001119baa706e9d70c26 new file mode 100644 index 000000000..0f244a8a2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/9018bc4f2cc3001119baa706e9d70c26 @@ -0,0 +1,1183 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/cb/b10e8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cb/b10e8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..202b5b72ee8ef7f5f30abb67708f31ef07bf1d44 GIT binary patch literal 370 zcmV-&0ge8NP)Km%VDkFce0=d)+vOWKIG} zhpvGvb*AhYN}o4m@H1o!d4o*tRBGZMkUCTWmkL{wB~SUlAntIEgw4Gc(!&*+NcHqe zdbonr;tjwaz@#r!B?pk5-j_#K1)p#z)*b-3QShBfQxGf+4==MNa*z{HXhG0C1P_4~ zh;-k(7eP#tUz1`!Wij$Dh)MD;xve&Fv5GXEp_kweUysY@i1cm8S?~wm($ky-rf?^L z4cuB_3%3%uz>Nj2a3et6#z@uGqTe`wK1>2-pyo{<@B~f=x)vOqS_S8F z{BbGcPm`Srko*>0TM51dS0?bbgq{a9*ucpHu=A!M^DM~~^Y@aViMI>L4{MrZFUa%^ Q4*&oF07*qoM6N<$f+pdR_W%F@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cc/4059872d15c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/4059872d15c3001119baa706e9d70c26 new file mode 100644 index 000000000..c0d05f482 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/4059872d15c3001119baa706e9d70c26 @@ -0,0 +1,1212 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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(); + } + + public void setContentParent(ViewGroup contentParent) { + mContentParent = contentParent; + } + + @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() { + installDecor(null); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + if (mDecor == null) { +// mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + mDecor = new RelativeLayout(mActivity); + } + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/cc/406d95885bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/406d95885bc300111ab8b17b137f3789 new file mode 100644 index 000000000..b240eaaad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/406d95885bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + float offsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindOffset, 0f); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0f); + (scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cc/e0bdb22952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/e0bdb22952c3001119baa706e9d70c26 new file mode 100644 index 000000000..04811d334 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cc/e0bdb22952c3001119baa706e9d70c26 @@ -0,0 +1,19 @@ + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cd/202ecd5df6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/202ecd5df6c500111689feaa37e8ab14 new file mode 100644 index 000000000..17b3f8dad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/202ecd5df6c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cd/709089ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/709089ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..9510eeb98 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/709089ff24c3001119baa706e9d70c26 @@ -0,0 +1,21 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cd/80e5b6db42c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/80e5b6db42c3001119baa706e9d70c26 new file mode 100644 index 000000000..1256b9bc7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/80e5b6db42c3001119baa706e9d70c26 @@ -0,0 +1,1181 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/cd/c0c9d4312bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/c0c9d4312bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..0d407568e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cd/c0c9d4312bc500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ce/00ae1d4746c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/00ae1d4746c3001119baa706e9d70c26 new file mode 100644 index 000000000..88db11879 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/00ae1d4746c3001119baa706e9d70c26 @@ -0,0 +1,1025 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.FragmentTransaction; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 { + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + + 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, ViewGroup decor) { + mActivity = activity; + 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) { + 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/ce/1084ff275cc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/1084ff275cc300111ab8b17b137f3789 new file mode 100644 index 000000000..2d4fb404a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/1084ff275cc300111ab8b17b137f3789 @@ -0,0 +1,134 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ce/332995ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/332995ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f02f5e433 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/332995ff24c3001119baa706e9d70c26 @@ -0,0 +1,72 @@ +package com.actionbarsherlock.app; + +import static com.actionbarsherlock.app.SherlockFragmentActivity.DEBUG; +import android.app.Activity; +import android.support.v4.app.Fragment; +import android.util.Log; +import com.actionbarsherlock.internal.view.menu.MenuItemMule; +import com.actionbarsherlock.internal.view.menu.MenuMule; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public class SherlockFragment extends Fragment { + private static final String TAG = "SherlockFragment"; + + private SherlockFragmentActivity mActivity; + + public SherlockFragmentActivity getSherlockActivity() { + return mActivity; + } + + @Override + public void onAttach(Activity activity) { + if (!(activity instanceof SherlockFragmentActivity)) { + throw new IllegalStateException(TAG + " must be attached to a SherlockFragmentActivity."); + } + mActivity = (SherlockFragmentActivity)activity; + + super.onAttach(activity); + } + + @Override + public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { + if (DEBUG) Log.d(TAG, "[onCreateOptionsMenu] menu: " + menu + ", inflater: " + inflater); + + if (menu instanceof MenuMule) { + onCreateOptionsMenu(((MenuMule)menu).unwrap(), mActivity.getSupportMenuInflater()); + } + } + + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //Nothing to see here. + } + + @Override + public final void onPrepareOptionsMenu(android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[onPrepareOptionsMenu] menu: " + menu); + + if (menu instanceof MenuMule) { + onPrepareOptionsMenu(((MenuMule)menu).unwrap()); + } + } + + public void onPrepareOptionsMenu(Menu menu) { + //Nothing to see here. + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + if (DEBUG) Log.d(TAG, "[onOptionsItemSelected] item: " + item); + + if (item instanceof MenuItemMule) { + return onOptionsItemSelected(((MenuItemMule)item).unwrap()); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + //Nothing to see here. + return false; + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ce/60fc548c52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/60fc548c52c3001119baa706e9d70c26 new file mode 100644 index 000000000..234aa78c1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/60fc548c52c3001119baa706e9d70c26 @@ -0,0 +1,25 @@ + + + + Action Bar Demo + An alternate title that is long + Toggle title + + Refresh + Search + Share + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ce/634b8eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/634b8eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6e77525d2dbbc1673145d60d775602c85264330d GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqEX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`6eo-U3d5>t~6?){p=$oZ!|i46oEul1LdSlBa@C*nY4{!0_J9HA2p woHspUxHx7V@R-QS6OjM!cw6swyHo~-e~lvMp^1B@1I=RaboFyt=akR{0Ay(_r~m)} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ce/d0af96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/d0af96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0354ad1ad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/d0af96ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/ce/e0d696ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/e0d696ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e090677a1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ce/e0d696ff24c3001119baa706e9d70c26 @@ -0,0 +1,572 @@ +/* + * 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) { + 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/.metadata/.plugins/org.eclipse.core.resources/.history/cf/706fcb505dc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/706fcb505dc300111ab8b17b137f3789 new file mode 100644 index 000000000..87b9ce6c7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/706fcb505dc300111ab8b17b137f3789 @@ -0,0 +1,206 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + blah = getWindow().getDecorView(); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cf/a05215462ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/a05215462ec3001119baa706e9d70c26 new file mode 100644 index 000000000..23c0653f8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/a05215462ec3001119baa706e9d70c26 @@ -0,0 +1,716 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +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.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 + * @version 4.0.0 + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + /** 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; + + /** + * 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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/cf/b29d8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/b29d8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6278eef472153576c2d1d3f8a39a7c66917724bf GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMg}h~fd(*my85}Sb4q9e0H>EG$N&HU literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/cf/d01a23110dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/d01a23110dc3001119baa706e9d70c26 new file mode 100644 index 000000000..832c67b6e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/cf/d01a23110dc3001119baa706e9d70c26 @@ -0,0 +1,17 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d/50bd96002bc500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d/50bd96002bc500111b2a8b7f47e59881 new file mode 100644 index 000000000..de731534f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d/50bd96002bc500111b2a8b7f47e59881 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffsetResource(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d/517795ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d/517795ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..74831a79e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d/517795ff24c3001119baa706e9d70c26 @@ -0,0 +1,318 @@ +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. + mActivity.startActionMode(wrapped); + + 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); + } + } + + 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(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d/60473271f7c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/d/60473271f7c500111689feaa37e8ab14 new file mode 100644 index 000000000..f04fd5740 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d/60473271f7c500111689feaa37e8ab14 @@ -0,0 +1,200 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.AdapterView.OnItemClickListener; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; +import com.slidingmenu.lib.app.SlidingActivity.MenuListItem; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuList; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuListAdapter; + +public class SlidingListActivity extends SherlockListActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d/c0a691ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d/c0a691ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c6a7d4d87c0e34d3e350e3c9438895b31d135b94 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^azGr$!3HF6SgS1tQk(@Ik;M!Q+?^oIXnykaTA*N_ zr;B4qM&sKX8+jWXcvu`~yS>=2qh%>1r1WJE1Ls*cJ{|veUO|(2 + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d0/92a293ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d0/92a293ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0b432448d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d0/92a293ff24c3001119baa706e9d70c26 @@ -0,0 +1,22 @@ + + + + + false + true + true + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d0/d06f13f90cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d0/d06f13f90cc3001119baa706e9d70c26 new file mode 100644 index 000000000..38f403331 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d0/d06f13f90cc3001119baa706e9d70c26 @@ -0,0 +1,777 @@ +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.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 + * @version 4.0.0 + */ +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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10443768f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10443768f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..4425a76e7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10443768f4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SherlockActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10ee022a31c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10ee022a31c500111b2a8b7f47e59881 new file mode 100644 index 000000000..03acabd74 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/10ee022a31c500111b2a8b7f47e59881 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this, getPreferenceManager()); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d1/406b197ef5c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/406b197ef5c500111689feaa37e8ab14 new file mode 100644 index 000000000..db8191bbb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/406b197ef5c500111689feaa37e8ab14 @@ -0,0 +1,5 @@ +package com.slidingmenu.lib.app; + +public abstract class SlidingActivityBase { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d1/c3538aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d1/c3538aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..bf3b9438b16543294498ba27e51d4e878c8ead5a GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Sd_7$pLn02py}Xh4fCCS+;oB*H z(}QQZt5vXQMa=PTZk@YrXXvE3+ofW5$)(cU#3WF_jrSY!c@8l>`*HAE!gKCvr?`99 W=bm|#aNiDSFoUP7pUXO@geCw#94y)Z literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d2/00f08aff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d2/00f08aff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4bc2683b156021ee7828ca108df3a39e0200e6ba GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Qo!3HFq_#{< parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d3/0075e3221fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d3/0075e3221fc3001119baa706e9d70c26 new file mode 100644 index 000000000..0fa4ca250 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d3/0075e3221fc3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/d3/b0f8be0224c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d3/b0f8be0224c500111b2a8b7f47e59881 new file mode 100644 index 000000000..5d32f0ed6 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d3/b0f8be0224c500111b2a8b7f47e59881 @@ -0,0 +1,205 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d3/d2cd91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d3/d2cd91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c6c3f1ec248835c16ee8a8f9d253769ea4196468 GIT binary patch literal 1309 zcmV+&1>*XNP)>2T29Hys?P&Vm zZA9*OOSNlf`Pu!y*8AUEO|D+e=9Pi3BR)agfw#}SukU>S5_JQH{fFX7qt#y26-7>F z^lg#%AL~){ay($Vl%dNK|ns=8F95J5u4IuT)_iO}FO5AO!x2YA-ev{((MiCMb95Z27y1N{d~<$0ZOiAzT-4$^Y~d8=D&GctVLiOE-HZCX=>916 zaB}eD93BUF6!cN|FY@&i`W7!}IIL?H*U-;b(9ZeC>T4fo-D~%;%Al$SM;o1{CK^c@ zLsL?U%;F5uW`mKV6p@jG8Wm~81rvcAg~E0r38^#=q@={j6{7*N{-mRal zZyi757l1u@+(UUVUpKQfbx4*^AEZ`NBGTk&djR!;W=;+8vR!2ZvkZUiF_Uw;@^@UHY_tFNo|bZ|HqK}~Z_0kB z>1@!nFOf~^{KOi&lvG5Os4i`3m5LaZ>S{(}C2cS_3u25qx+GSC0x^F*mC<6C%zjX} z`(@Gi@=yT|C0D;bu>bAn+W30Hh5ZfH4VVpRc=$wP71`a_ciV~TTQkNXRQHQat7toU zZx*3Z?Q~QYQO|ZUR_Tl#qXtzIiPWWo(#}&aV(i6KuEST$lYVRUVscgaEz?@VCh+@z zYdAdahv=OS&fP(?9$16?`l0%F3gfnP`B71?hw4@2e4pjZouU=>X|R*`N-YD-DJj}uU$#5 zV>X}RzD~bXHhFf?KK=4JTCWrMiS*`U`G2n9l*Y@cp7B$uQwuKJNIF$ + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d5/c047458a2ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d5/c047458a2ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..f933c8c5f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d5/c047458a2ac500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSlidingMenu().setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d6/60c50ddd23c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d6/60c50ddd23c500111b2a8b7f47e59881 new file mode 100644 index 000000000..84fb04993 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d6/60c50ddd23c500111b2a8b7f47e59881 @@ -0,0 +1,38 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d6/614b8eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d6/614b8eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..3bf8e03623c94b68d31963ffe7e59c72c3dcc059 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqEX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`86o-U3d5>t~CW>mH@a{g&g;s7!l1y4Byva-KaJLVIiI)OpBYodjS ofJx&-C1HsL_x|*Yp0_#7zz}{&aC*>dO_0?Lp00i_>zopr00f~Zw*UYD literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d6/b000bdac16c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d6/b000bdac16c3001119baa706e9d70c26 new file mode 100644 index 000000000..f2ae2b0d3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d6/b000bdac16c3001119baa706e9d70c26 @@ -0,0 +1,1146 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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(mDecor); + return aActionBar; + } + + private void initActionBar(ViewGroup decor) { + 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, decor); + + 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(mDecor); + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor(ViewGroup decor) { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + mDecor = decor; + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + installDecor(decor); + ViewGroup returned = generateLayout(); + initActionBar(decor); + return returned; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/d7/a0e78eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d7/a0e78eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4055f70539b60de832611c523a1dc509e170dcba GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^59s(?g`O^sAs(G?r*GssWFX)$e`(35d_EZ~i&w|H<&_`ZD(+MedV5zj zu-#_I+lqbxCf!wDY`(!qq|2YPZ`s2sD|KqW({JG~4*WL+Cpx;A`7$XPF&b}JE9dda zdDh0P2cC5-%kKDDBus2)4y)97FmX3?+)izQiL;plcWMSG#q&-%rTF<%+zn>y2h*Mj yizj?!^E*(P`ureMOz-ZiFXWg1cX%y7!FpSm=AYI1UI{?QGI+ZBxvX + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d8/a2c993ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/d8/a2c993ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..0a409756c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d8/a2c993ff24c3001119baa706e9d70c26 @@ -0,0 +1,50 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + + 2 + + + 56dip + + + 64dip + + + 65% + + 95% + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/d9/e0175dd428c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/d9/e0175dd428c500111b2a8b7f47e59881 new file mode 100644 index 000000000..29326ece8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/d9/e0175dd428c500111b2a8b7f47e59881 @@ -0,0 +1,38 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + CheckBoxPreference cbp = new CheckBoxPreference(getContext()); + cat.addPreference(preference); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/da/20cc06314ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/da/20cc06314ec3001119baa706e9d70c26 new file mode 100644 index 000000000..1c56b2deb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/da/20cc06314ec3001119baa706e9d70c26 @@ -0,0 +1,6 @@ + +

+ + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/da/709dc68093c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/da/709dc68093c500111b2a8b7f47e59881 new file mode 100644 index 000000000..f90649fa2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/da/709dc68093c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/db/70c595ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/db/70c595ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..02ddff48d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/db/70c595ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/db/713698ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/db/713698ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..969459749 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/db/713698ff24c3001119baa706e9d70c26 @@ -0,0 +1,472 @@ +/* + * 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; + + /** + * Constructs a menu inflater. + * + * @see Activity#getMenuInflater() + */ + public MenuInflater(Context context) { + mContext = context; + 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 Context mContext; + private Method mMethod; + + public InflatedOnMenuItemClickListener(Context context, String methodName) { + mContext = context; + Class c = context.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(mContext, item); + } else { + mMethod.invoke(mContext, 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); + itemActionProviderClassName = a.getString(R.styleable.SherlockMenuItem_android_actionProviderClass); + + 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(mContext, 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/.metadata/.plugins/org.eclipse.core.resources/.history/db/e1f491ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/db/e1f491ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..205b66e2cdef686c5ed6369b14e64b38d0182984 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr?*8<0#p>+uXou@pObhHwBu4M$1`kk47*5n0T@ zz}*SLjOHg#uLTN5dAc};So9|U`2XLYnVI=;y-5$#f-D2o4GsT&Tr`prfMCHsr=)`p zy9zZlQWAk&gL|Kjh|gcN+0MxMkn!S`=@A+#%ic(Om>d23|9^ht#EF9It^fc3f1ZP3 Y!dJ=4-o~HPfwnMsy85}Sb4q9e06h#o+yDRo literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/dc/10ab82973dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/10ab82973dc3001119baa706e9d70c26 new file mode 100644 index 000000000..e3ad6f8a2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/10ab82973dc3001119baa706e9d70c26 @@ -0,0 +1,20 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/dc/90a293ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/90a293ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..c64ef141b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/90a293ff24c3001119baa706e9d70c26 @@ -0,0 +1,49 @@ + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/dc/c0f743ac95c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/c0f743ac95c500111b2a8b7f47e59881 new file mode 100644 index 000000000..bc2da57b8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/c0f743ac95c500111b2a8b7f47e59881 @@ -0,0 +1,39 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/dc/f06061c914c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/f06061c914c3001119baa706e9d70c26 new file mode 100644 index 000000000..cbc9b7c6e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/dc/f06061c914c3001119baa706e9d70c26 @@ -0,0 +1,760 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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 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. + *

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/.metadata/.plugins/org.eclipse.core.resources/.history/f/908498ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f/908498ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..1314248a4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f/908498ff24c3001119baa706e9d70c26 @@ -0,0 +1,39 @@ +package com.actionbarsherlock.internal; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static com.actionbarsherlock.internal.ActionBarSherlockCompat.cleanActivityName; +import com.xtremelabs.robolectric.RobolectricTestRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(RobolectricTestRunner.class) +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/.metadata/.plugins/org.eclipse.core.resources/.history/f/f31b92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f/f31b92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..126637d1194f1d6609787774fb140818eaa4ba1f GIT binary patch literal 381 zcmV-@0fPRCP)hG*08Y#N?T!?S64w!;lKvy+*1?>p3RGdlx#190x$dzj&7b^-9QUftoB@I?dG z(l;!l|3;oEFaA*ajtwD8hd-6>9*;+5M`bO2!%}+FXrQS0p3;u)|QJUO}XO$+G;+dssck%4fw5xbU zX__uxRhp)XSC*#P;_m>iSbo@k`^^CW{9xcU{p|2h0AG{O_A~&$L7!btFK9(XM7DX= bKfeD1iaRu(IeFS@00000NkvXXu0mjfR7Ip< literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f0/104c97ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/104c97ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..323ba2d88 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/104c97ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/f0/213e8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/213e8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..79e56f522b2837bd9f579b28f037ad5eafaaee8e GIT binary patch literal 1414 zcmV;11$p|3P)cSnqT^=WQ7*OFqW%ysfqGq3fLYCng$eebY1E zq0h)!qMt>^T{!1KLrdv5=!(bMwnfb7mMF4BgVA@!3k##^X|etG%o8VLfn)&kp1$5* zAHx|3EF9@?)w)=}!OothSF(h}LSVs2n}u~V8rR2gA&m?6GFm9LT5i!5ovh2$`aOLf zDMwpCv(UIN+s(qhT71rU;E=VYR%2(wIy9)U9BqNMU?EvKj~0!zxmxOREjkZzh+iq_n}2*GaEP(@ILD!5 zWBguqUH^M`clY;tz5a@wsI&tR0g7j89WEv$&WS`s3jmAj>+65+@9$R+4-crSDsl+t zoXD~ai^by4tE;Qe>-G9CHN@f2j4rXz#$jzQA^^+B$H$Mix3`1-5a+ZsO@p#5Q53}= z0G4QnFC7vyL_!;@%<@Jv>_k)mSUx>Hz18n=PE3d}%kYsC@*I)N0NNv^lI%s;wg9j! z%knLLgEIoQ+bysY63^&#(^_eOc(NT6QxTdoZI(#S<~ro`ne!tS(gH7T&zUX-UZRk7 zy|5!F77`FowzZg?X(M)KAw}<4SRP51e8qZ>m)V;$Z3?tS#CiaZ^hhEi?U_=yRh(%c zcGk9kwMUBGYjYt@pHyCSltyExNUHHFevMy@-l#r~QEjQ;(4?Q~r4samHh{FF{bU7StYxgeBAZQ`6E7N`VLYGS_ z;oj>aHT`D+d1$*FJhVBd!G+`uf(ywR1Q(Js2reXN5G)~C&xiARXWFDHmGF81Z6U>K z;#g%)oXa8RP+ENtZO$MZBP0)Pm&4Jv?h_KbHF>VdnKo?a-t;CVB(9^gh389`0#_~3 z>r7%ovdX{d8amFjk%uF>Vp~*9sp-GKg_vAO(?{&AZLdjA|Mdo3?oA8H>)1>mc|==# zB~EQxV&cD40$n%8&w#s-rjOWJ+ddiIQXYxR!^y#)tE&3)24CJ80l~J_MCXPu>Ml3AI+9BHcJ4%0r(Kw z@2dYHj4#nGKH!fqjRVUuh**Aw_CvMrs{b>Lm!YwzO4di>6N@*}Phg5Tw&B1fy2S@v zNaMh=r`Sx3>1SxA8q+hl==5I;NtblfC(XkF^KkH7ZKuDGcq0~@mC!ryi=K7WXgde? zOwz>rq{P&!A!(hIr~D!&pe-W#G7`?LQYh|`P7hzs(O!weT#2|xih3m$l64(P7wFd8 z$(YnkvI-Blh{l8EAha{kf+|%%mTX6hk;YCcRo{6`6g>|oKBz>Tb24JLyVyI4p!izS z!8wv9b%$RIiIZ@y?B&nGjRPyvaF~-xlb-U|=!P~^8?n&FNw@wIvQA!p;xDy1AK0dR zu~CaAl^btMM>A?9->NQ&|AnVmzdt!!WF>xutSl`;$84s2a_=ari#ecl- zo|KSyJXTD=1$2JI1Ql!6el7Y8-dCZ-i%gs^mMBu<;eLzP8a;YIXA&Hxi>7JtAFa#2 UvCQ(L;{X5v07*qoM6N<$g1g$KMgRZ+ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f0/40f1ff8d26c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/40f1ff8d26c3001119baa706e9d70c26 new file mode 100644 index 000000000..7ce5efe6f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/40f1ff8d26c3001119baa706e9d70c26 @@ -0,0 +1,1182 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/f0/801e582a27c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/801e582a27c500111b2a8b7f47e59881 new file mode 100644 index 000000000..aa1907f12 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/801e582a27c500111b2a8b7f47e59881 @@ -0,0 +1,16 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + + public MenuScreen(Context context) { + super(context); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f0/b042b8554ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/b042b8554ec3001119baa706e9d70c26 new file mode 100644 index 000000000..89fe3f258 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/b042b8554ec3001119baa706e9d70c26 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f0/b19d8cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/b19d8cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..d57df98b501944b4ba63623766c396b5bccc29ee GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMg 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/f0/d075347f50c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/d075347f50c3001119baa706e9d70c26 new file mode 100644 index 000000000..9f775cb9b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f0/d075347f50c3001119baa706e9d70c26 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f1/81998eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f1/81998eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4bb22f0e10e621ef31f16100b3f682a09565c65d GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol;0U|59*B=E^EX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`7}o-U3d5>u0Z{Qqyy%*=eaUL!352pYN+StcB)SJP>#V9b+U;=REk xGyYWXA=VWyWA+H$a1!q?zNqxd-sOcoGlO8KcyMa*40E7i44$rjF6*2UngAF=E + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f2/d2af96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f2/d2af96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..7a81717e9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f2/d2af96ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/f3/008829b329c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/008829b329c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2bf0f2afd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/008829b329c500111b2a8b7f47e59881 @@ -0,0 +1,210 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + mMenuScreen = new MenuScreen(this); + setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveView(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + return mSlidingMenu.getBehindOffset(); + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f3/2094de3c52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/2094de3c52c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..03eb53d65e36db45c8736a3321bc6b197741c5fc GIT binary patch literal 2406 zcmaJ@dpy&7AD>ILky|&TPJV{uva48IRegv$mJXq zQl6AlLMp^lL`rf?J*^UYo)V5aovoA3^T*Tk`@Md@@Avb4z2EQ8^^b4bE)Qod4MPnW z45sDkLi19r+m#=Dsp4P7IXI$N48(MQu{RVdj$#Tym;)OM0RdMYGYs?sne3Q@cR+g> zObx~H@fZ6u+{rA6hhZu)m}s6r!G^)?w?zw>tO!sHgn(fjJ_R*>tr-Py*c8-mTLz9H zpn~BXmqS9(`;dnZ>re!X#71q~3fM=J6#_g^%mku&T)v1LO+kIpB`fyIV=M~z0ue`0 zP=5vG&)5Y}At4CZVsK~{&JG9I;W2odO++Hm8X(~CI4q8U#S_qYBH4yO#^Hdk4@%)p z$POiY(VV{eQdksJxL7P8W3f?DQJ5$j3?vN0;z=ZuQiDK1D-dW=3}4KQM)O4`iwZPQ z#1e7@Vh+Ryl#0v{C{j#8DI)zV1)kuWEMN4sOp1bGqnQFM9)nY+vY zy}-ZY{hz`jpBMp%^#Vmuq>!a(T&RiCm4HkYf=n?a^noDmVik9VLt;o24haCNw=KY6 zvN(LD{RPipkX`vAF_X^%U1=1QLIK0!u*tSm0*OY#543kghT=%LVlS=`4y{ z_+fU|*QQIQ|9LN}guXqe%c?>KH7-nkzEF3#CT{$g)Ud<2RhKF4*^#PuG;R85il)N)uGQ!YyY%lI1 zh1jTkY%|jJgD2Sn65XptCFqEh?dDId8ZC&AZ|2?8dx&@Nb*LgDHawL5 z+uXs{Ey^GJ=IyD!xrRY>^RQ=n6fR`N(a^#@EjmR~q)K{@zI&Ih{k9XWQV%Yso z|983U?4zK^_-#VK8?O?$&FX! zvi`oK#+#wH$?D@SW$LxPbt(A6Dk_-)+XC9JzAzo+%Cra@3TFze=gr1aQU}R{pVhk0 zgvn2t?meOsUOVLhp?pN3T3u>4B=dhm4_J%f@{YoW9D`tQ1_ zQt$CUDoi>h{BkTu z-0aQVz6hOt@&Bevt%HRPMY}$9BAC^I`>RmEbe;h>H@VigEBgTaCw@~v8bh;e=RnoJ zE**eJ`wmTSt|A1MI}f}*yFzUx5HX+FB`Pr8!1c}L@_9!OeXJSF2`VVtbt6_y@9hKm z+y&R6@dtGW-~(%BWrCo~dD2LwlQ_MfqVhu?T5kxhanxR!E_HBr<5she)Re+I413-8 zrS6>(Rxa(d<4$ZUn|Q1s>;BLm8`-!t>WQOjlZ@v&^PdZIcE5Z1t_M!!ZM_xgkSme! zbnDH`xZ(*ap!&SP1J&~OP8K}_?w`zvuZlB%FF~rV*ZWbw8}sz{a?5jVc6%huj6OSb z^-F5MdTktfDkhDC)GDr%N=3Dxe=hcLkamtn#2uu6V}i!SQOnVjRj12>sruZXM+(vs zVZR*HWuBU`g?wJuREpKe#eU^ASIj)$)zuiu&?%+`n&Sr7hSnKwnUqb!&64b99v0d= z){PNaT3*`S$duL?-=U)MBOUk2cb8{`N9gc&uD#Hdzp;~P5gQ!j=l5pGqqp;!mVBRw zzlIDYOxZLvSGa{ODfAu9(+~))UnauCe5MTygLjVg84SDFYqJidhfJ2hf@G!F*78mf z8%sRTpT$&<^fYfIEHX+38wM>RL*oY|Qn zN`flKU9}z?*uCHFOWv68Bx^#H6wfZq=_WsMaAgd>D&ZTgRvBdECtIc9D`mHFL&RnJ zcdL6n1Fnp%Xpe+L6hC9cNl&e#rGP@)7!n=w>S@F>#e@anRa#&q5|^Mg#m?H zWVg8zr>@Y5p7>2}pDqpPkKMfYsU@zXFnAgHVpFW=+Q6>Q$or?8N&Ba76MR*Ruk8&@ z2urp4IR9hbSg4u`!JofTv%F^Jd>sRWR^6k%>B>i|7TCV3-8Q#wwa+VWKCW~R+BwJI G#6JPFT 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(); + 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/.metadata/.plugins/org.eclipse.core.resources/.history/f3/60cf24294ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/60cf24294ac3001119baa706e9d70c26 new file mode 100644 index 000000000..c9b5a6472 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/60cf24294ac3001119baa706e9d70c26 @@ -0,0 +1,121 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f3/a0ea34e4f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/a0ea34e4f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..13c55f60c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f3/a0ea34e4f8c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f4/70018cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f4/70018cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..924a99d173082ba58ca7527822359f228bb14dec GIT binary patch literal 1061 zcmV+=1ls$FP)#d)-&;4-At916hopygyW1WQa|lkCWZ4-q&QLYwjy>%Jd>?UvK6*fy zdt!`Ep~K-gOUxeEG;B7TCA&L&Y`5FR`f3tF5S^VH!lJsKJqkfK0&PN7nPcRS?`4Ev z7V~vPKouy~L@5%v*=&-(hy0cgM*ETwjWz&8F3NVhH7#V4$3+kVgi2lPw-adOTXm|2 z;f`P0rx+seIw-H@dwPaOx@-q(hY$i2BS4u1XM~+%LI5%mN(D;0XOsl63U@~43e6EU z5mrW96C~;L2O}H%p$jmGc5)7LM&^oyAacV=14{s_wp`K^YIpyDFEM02mXk3OSEw-p zdORS~SGTvf|Cjl{`o#71_3u-2KzcK(ZU7La5JAil5&>9olp#5yVJhG_L?OnQ2x7(v zIfg2+Q2z$cZ7gkJK~)>%8)`3CJSNBlBGKwWz;6QnLDPCN+(q9 zAJ*09wM4d_hZLYxWa z2;mvCbu@F-B1H21)loz{?U-+?@nqk8kw`Vm31QkJFg_V%{OMfZr8mlq(-<|uJGVoHpVClAlh&-bsduQ(hI zi(GsU`1tt1hf_X{d`3<68b|S{tXYwd2YXzXl8Izg4y^21 zp<@H92ON{kB3P1HizBE$;EP~xzks74y{^`3Ur7(FmPO0@t2+WXW`VN|Gc9|AJ43ds z=_5ZJGT6$YN8bIa6HYZ^jFIn`&>W#9La9l$?6@3`ET&WsUkjFK0@?|yO)(6`*1l_s~_L1z$~& z@jZM)qqe)$B+Pe}79nG2sji9uR0#8Z){~%#a(p4yPG;@1CipK8G=YCTO^$u*mj`Me f=rGa5Ym5<}3Pv>t$oVA_00000NkvXXu0mjf+qu}} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f4/80386628f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/f4/80386628f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..ab0fbe829 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f4/80386628f6c500111689feaa37e8ab14 @@ -0,0 +1,17 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + public void toggle(); + + public void showAbove(); + + public void showBehind(); + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f4/b20e8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f4/b20e8fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6de0ba8841d25f20f12e14002ecc4c9ec6a7b2f8 GIT binary patch literal 370 zcmV-&0ge8NP)Kmp@CxKpa3{epU;uAYD{w zoy1-2XXsG+d5c4J(@pInLg`pK=_I6J(k2d`5V?BE{Yj@j2pl)OcgK;0qd#7akgCKEJ@PeExDlrpx^Tf8?8gJ#K-Da<_nm z+&*9_w+lGPs|OtA)dC)JfQDKAb-?t#>nbk~ygr<>n4NOeOiNA8R)UE3F)|0PZr-`P z{wS3Lh~%_Rw1t=h$DO2-+|>0Ilo0LghZEP}j*Edw;7F{TKbM3p1iOHI0}cLp61dt? QIsgCw07*qoM6N<$f;wQ9<^TWy literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f5/00717c57f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/00717c57f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..6e485a018 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/00717c57f8c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f5/203e8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/203e8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ae21b760fb1ebecac3389164251b0fa14f580f5a GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SqC8z3Ln02py>gKAfB^?4dC zy{Qwe+I<(;Zrk3}qFy7o$Hqotreyxi(D>i`gF-*@tj&^T;Xws!Omj@dZ?l#4Y_?*} ivA^-x{8q}NM@;fbHo20HF^oW47(8A5T-G@yGywny6)bE3 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f5/2072c80454c3001115d2d454e05194c5 b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/2072c80454c3001115d2d454e05194c5 new file mode 100644 index 000000000..a306a3cbd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/2072c80454c3001115d2d454e05194c5 @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f5/901396ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/901396ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..84f7504ab --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f5/901396ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/f6/002ffafc50c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/002ffafc50c3001119baa706e9d70c26 new file mode 100644 index 000000000..c7d6cead0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/002ffafc50c3001119baa706e9d70c26 @@ -0,0 +1,21 @@ + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f6/00e68715f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/00e68715f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..42d451964 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/00e68715f6c500111689feaa37e8ab14 @@ -0,0 +1,12 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public SlidingMenu getSlidingMenu(); + + boolean isStatic(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f6/90abdc014ec3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/90abdc014ec3001119baa706e9d70c26 new file mode 100644 index 000000000..6a5ddf1ef --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f6/90abdc014ec3001119baa706e9d70c26 @@ -0,0 +1,20 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = this.getWindow().getDecorView(); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f7/50c9c9910cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/50c9c9910cc3001119baa706e9d70c26 new file mode 100644 index 000000000..71e40300a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/50c9c9910cc3001119baa706e9d70c26 @@ -0,0 +1,253 @@ +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 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/.metadata/.plugins/org.eclipse.core.resources/.history/f7/e0b5afb7f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/e0b5afb7f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..c61c8c9e2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/e0b5afb7f9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f7/f0ec1f0e0dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/f0ec1f0e0dc3001119baa706e9d70c26 new file mode 100644 index 000000000..44c479b38 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f7/f0ec1f0e0dc3001119baa706e9d70c26 @@ -0,0 +1,20 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; + +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f8/11e6ec4e4ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/11e6ec4e4ac3001119baa706e9d70c26 new file mode 100644 index 000000000..2d59ff729 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/11e6ec4e4ac3001119baa706e9d70c26 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + --> + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f8/5067ce9f5bc300111ab8b17b137f3789 b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/5067ce9f5bc300111ab8b17b137f3789 new file mode 100644 index 000000000..98b796ccf --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/5067ce9f5bc300111ab8b17b137f3789 @@ -0,0 +1,138 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewAbove.setContent(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mViewBehind.setContent(inflater.inflate(viewBehind, this)); + } + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset((int) offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { +// mViewBehind.setScrollScale(f); + mViewAbove.setScrollScale(f); + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f8/d0cef5e90cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/d0cef5e90cc3001119baa706e9d70c26 new file mode 100644 index 000000000..3a4a44675 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f8/d0cef5e90cc3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/f9/44df92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f9/44df92ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..39aca3a8d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f9/44df92ff24c3001119baa706e9d70c26 @@ -0,0 +1,26 @@ + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f9/61da8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f9/61da8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f6fd30dcdc9c39c836e509486854f9da03486892 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^;y~=k!3HF){@Qy1DVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?cuyC{kcif|*A4j^95`Gq9-KV8B6o6ra`I!Z80pW;7d5zZGhRBg zm{FnhT6Xzih3ZMUGkfBc^kAT_eS7{3zPQ8d#DAmThere 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/.metadata/.plugins/org.eclipse.core.resources/.history/f9/a005ca4d26c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/f9/a005ca4d26c500111b2a8b7f47e59881 new file mode 100644 index 000000000..4be5769d2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/f9/a005ca4d26c500111b2a8b7f47e59881 @@ -0,0 +1,7 @@ +package com.slidingmenu.lib; + +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fa/004a499242c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fa/004a499242c3001119baa706e9d70c26 new file mode 100644 index 000000000..77e9781c3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fa/004a499242c3001119baa706e9d70c26 @@ -0,0 +1,1181 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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; + +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + 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(); + } + + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + view.getId()); + + 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(); + } + + public int plusOne() { + return 1; + } + + public void generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/fa/70e390ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fa/70e390ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..8ded62fb7b6a27a86f7b532c9a2b5a4ae999d34c GIT binary patch literal 741 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE&~JOTTd6q5Rc^#N8xy%NgI}`eR{7o3SVw~oLF?DlhO#(rS&-V`^Q!s%)gPgzJD$(6 zlPX(2b^RHIj&o60rR$>g!|G>TRxtl*e|^4a{T&6ax|r;1#_KA};b_owfAXfrk8RFR$o&QDy{Vn>#x#sulW#~7Jq)- z)TH!~FS$Xsf0AE4joN$h`JQ|K8Rwjx@86b-rgDVb@NxHUL6S>yvXNP=t#&QB{TPb^Ah ka7@WhN>%X8O-xS>N=;0uEIgTN160J|>FVdQ&MBb@0GkggF#rGn literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fa/a2768cff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fa/a2768cff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..955a2f34061ae8ac853050da355f89409fa0a784 GIT binary patch literal 464 zcmV;>0WbcEP)C3<00004b3#c}2nYxW zd0`Pl=$b2!s#>@tS z$Y#JV#)+K6SU+tW#+_RkXYzpRi_e9eTN!5>F{(z4su81V#Hi{OLkTB`etUYuM1<4( zFh4)_STHCiBAh-(+2ze7j|0M$*V@)G5^^0JhFHh^fzV_7Tf?-4Si|T*tYCB@#xY$W zMloF>#xN!zMlhxzoiQdMoiL^$+87%UEsQNlYm7|@05m?}iO1-}bYl(D3Ue3c7gw}A zD?zp;CtICi-;5NDtN#ybjCs$)&yQmArGt<$4!&l7(HXO5p7J23`oDJvM + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fc/9080fd0f4fc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fc/9080fd0f4fc3001119baa706e9d70c26 new file mode 100644 index 000000000..e047d4504 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fc/9080fd0f4fc3001119baa706e9d70c26 @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fc/f0d090c514c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fc/f0d090c514c3001119baa706e9d70c26 new file mode 100644 index 000000000..1f4ca2f54 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fc/f0d090c514c3001119baa706e9d70c26 @@ -0,0 +1,778 @@ +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.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 + * @version 4.0.0 + */ +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); + } + + + /** + *

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) {} + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/fd/30f488ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/30f488ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e4de5491f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/30f488ff24c3001119baa706e9d70c26 @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fd/5056cd32f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/5056cd32f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..74a4ce79d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/5056cd32f6c500111689feaa37e8ab14 @@ -0,0 +1,198 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fd/50c1c6d325c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/50c1c6d325c3001119baa706e9d70c26 new file mode 100644 index 000000000..d912a7d90 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/50c1c6d325c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + ((ActionBarSherlockCompat)this.getSherlock()).setContent(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fd/804c0dfe2bc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/804c0dfe2bc3001119baa706e9d70c26 new file mode 100644 index 000000000..be3334ef7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/804c0dfe2bc3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fd/d0f3e8b693c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/d0f3e8b693c500111b2a8b7f47e59881 new file mode 100644 index 000000000..c2fbea293 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fd/d0f3e8b693c500111b2a8b7f47e59881 @@ -0,0 +1,197 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveView(mainView); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fe/b029bb50f8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/b029bb50f8c500111689feaa37e8ab14 new file mode 100644 index 000000000..6e485a018 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/b029bb50f8c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockListActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends SherlockListActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingListActivity.this.getLayoutInflater(). + inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fe/d05c8fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/d05c8fff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..6bcbdb83f --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/d05c8fff24c3001119baa706e9d70c26 @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/fe/e09b7f8424c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/e09b7f8424c3001119baa706e9d70c26 new file mode 100644 index 000000000..e396e6cee --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/fe/e09b7f8424c3001119baa706e9d70c26 @@ -0,0 +1,1144 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.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.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.RelativeLayout; +import android.widget.TextView; + +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 = 14) +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; + + + 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; + + /* 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, mDecor); + + 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; + } + + return wActionBar.hideOverflowMenu(); + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + } + + @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 (aActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) { + if (mActionMode == null) { + if (wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } else { + wActionBar.showOverflowMenu(); + } + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // 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); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + 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 (mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + public ViewGroup generateLayout(ViewGroup decor) { + mDecor = decor; + installDecor(); + initActionBar(); + return mContentParent; + } + + public 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); + // TODO add the view to the not decor + 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/.metadata/.plugins/org.eclipse.core.resources/.history/ff/109445830ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ff/109445830ac3001119baa706e9d70c26 new file mode 100644 index 000000000..b8343f12a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ff/109445830ac3001119baa706e9d70c26 @@ -0,0 +1,1472 @@ +package com.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +public class CustomViewBehind extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + private boolean mEnabled = true; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + private int mDecorChildCount; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewBehind#SCROLL_STATE_IDLE + * @see CustomViewBehind#SCROLL_STATE_DRAGGING + * @see CustomViewBehind#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewBehind(Context context) { + super(context); + initCustomViewBehind(); + } + + public CustomViewBehind(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewBehind(); + } + + void initCustomViewBehind() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + setAdapter(new CustomPagerAdapter()); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mContent.position, mContent.object); + mAdapter.finishUpdate(this); + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + return 0; + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getScrollX() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + ViewGroup.LayoutParams params = getLayoutParams(); + return params.width; + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + private ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + public void setContent(View v) { + mAdapter.setBehind(v); + setBackgroundDrawable(v.getBackground()); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + int decorCount = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + if (lp.isDecor) { + decorCount++; + childLeft = getChildLeft(i); + int childWidth = child.getMeasuredWidth(); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } else if ((ii = infoForChild(child)) != null) { + childTop = paddingTop; + if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() + + "x" + child.getMeasuredHeight()); + // TODO PADDING! + childLeft = getChildLeft(i); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mDecorChildCount = decorCount; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. + if (mDecorChildCount > 0) { + final int scrollX = getScrollX(); + int paddingLeft = getPaddingLeft(); + int paddingRight = getPaddingRight(); + final int width = getWidth(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) continue; + + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + int childLeft = 0; + switch (hgrav) { + default: + childLeft = paddingLeft; + break; + case Gravity.LEFT: + childLeft = paddingLeft; + paddingLeft += child.getWidth(); + break; + case Gravity.CENTER_HORIZONTAL: + childLeft = Math.max((width - child.getMeasuredWidth()) / 2, + paddingLeft); + break; + case Gravity.RIGHT: + childLeft = width - paddingRight - child.getMeasuredWidth(); + paddingRight += child.getMeasuredWidth(); + break; + } + childLeft += scrollX; + + final int childOffset = childLeft - child.getLeft(); + if (childOffset != 0) { + child.offsetLeftAndRight(childOffset); + } + } + } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + // we don't want to steal touches from our children + return false; + } + + public boolean onTouchEvent(MotionEvent ev) { + // we don't want to handle touch events here + return false; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(0); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (width != 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ff/40d5f01c54c3001115d2d454e05194c5 b/.metadata/.plugins/org.eclipse.core.resources/.history/ff/40d5f01c54c3001115d2d454e05194c5 new file mode 100644 index 000000000..c1aac2a5a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ff/40d5f01c54c3001115d2d454e05194c5 @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/30/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/30/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..f5dfbcf78bad458166064f930f54444579844c68 GIT binary patch literal 228 zcmZ{eF$w}P5JhMA0A4^F58%Yk1BktBWfx*Hgn=ZpOcHT#FSueMSpE0DGfU z&BLWm^^lxKGVWfj4V2wN{1T?r~2kOLw4#B(Kdp~3DfIZL_abP3!*;HMB{hT8M!pl;u0!Fu1y!5s7hB)D`EQ7uvzm}WhQM4n13Ghey;eV@&aJm BP|^SZ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/32/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/32/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..c90dce1a6c97d1716e960ff916249a62314ad85f GIT binary patch literal 166 zcmX|(K?=e!5JjgRz(crqvh)DrUb=EuV)H2jNv6!CrM6n_-Q)B b+D>8A!m%b(Nh}HfDZZWaT}#pWD)|UMP>?%W literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/3a/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/3a/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..e5f29d8df70e5839fe4b81524d02ab30f4265509 GIT binary patch literal 304 zcmbu4!3x4K5Jb2A0RN<$llTGRU3&5s(qt(MNw#cKY5v|~#k1gX24?0>2LL?`MyZ(S znyhu$qSKj-n~Jr?D^a%2SC(uir?{mET@M%08OcXp3gODgxsqlVQEBE^vI_17M)>FuM^$vuDZR7z-JDW0LwP-^j4$2|ZU~}OSJIb-LroFKx za`&8J_P7rm6LA@#(b1y{hNCrT4ZWmv=Q8f1_c0v3dw{Tf4|Egxl_w?4e_53&u=r5+ Tx-wHJeNqE~XvOph_&f9lse*MA literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/54/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/54/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..996e94b35ee2f9388fb40db8f32a4647aec05563 GIT binary patch literal 273 zcmbu4u@1s83`AW%fPa7;hXDz8#Ev?#RcT`?OG#YWDbT+MQN+f?cqiT6y9xjnuy#u3 zZa$7=oBQst4TJNoHBBe^$~`_(glYkM(H^ObJQ(4~$hnYaA5p1iD>`9KCZl$A3S30% xj}6ONpH&9ZGJ)$Pq0d2u19G5mDZO)sM@dQYCB-=it6zYvNVJ)+dR>9Pr=GS&Uj+aF literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/62/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/62/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..bbe7eb30713697c3f9e2a45ca5de0f1eb5cb2e17 GIT binary patch literal 2416 zcmcJRO-{ow5QSY1z=l&GzyXP$13>qvD|VJ+59z43CmK5~<@7{NDg7}5gu6_nA9c^r-z|N4-Gte{Rm9mZ|A|i^})Yc78=394Z98&4}GVr^NV9A!&Cc$#;LD zJ8Y(@sQB{?KJ{V5VA1H$O&3Mx6r<_a8#?8Qf#$%kjuuBUe4J6do9$YgS;N!?s}k!F zF(HLvn(_;{$&7;uyxN*#)ePm)*S|%7l~SQ2ca<>}Mj(QjGvXi$`*D!-^Gtv&+zjs*CnH5~{4hweUx YI!^ZN$w>5LscL?L?T-ZSXU$W=9dI1QeE99MP<^!HRM;<&S#-3|ac2*Johw)9Rz zq0_7HLmE8B*>u_(k3yLjiBBzxA1Tls;H)+wjfH0?To}1FvYHASP3+B9yp!u#WS#AYZ1Nv6!C(%#-;#m$HJ;r(9$Kn1N+GWYgz zCaa^@k+#gCPGREu)STPp(lpM$tnULS%7#mdP#xeZIwB2`CnKC0ITzCGBPxw-MOW;| rWY&T1fs1JOtKqowLuDc@E4V=tZkH+?kOTck>FXKZBqhnu6nF6h>LWmy literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/81/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/81/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..f2ce7a4af2a60e365f558ab3cd959f83456d908e GIT binary patch literal 179 zcmX|(K?=e^3;b=_w7(ZrJkG#O0{{(#VC3Ny^FrR{ zXcM)PW^NDN@wA@1F2tt~Lt>%gxJrg*2N$&oY0Nx3;ljwJl9iazXkxFnVNb4$jdV*~ l)%u@?{g>~iGg;jrj4BvQGUbGv=s%@T=Xg~SEf2}x@C~W>KF0t6 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/93/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/93/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..a280f9b58b2d55a82272731fde0d9724c0147233 GIT binary patch literal 166 zcmX|(K?(vf3;LHgFc5k*37e2sdeI=TP= literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/cb/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/cb/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..0f968eca04d7aecc855d9352cf17b7a5c89371c9 GIT binary patch literal 166 zcmX|(K?=e!5CAtmz(;s@(~I~3@h&}iD=}HhLXs`JiQ3-_Ry@wYi~|4%2d`xQ8FD8( zzD~oC79SoqO^FLt!*|Kxc5oJ*kz(e>2shMpMweq literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d6/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d6/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..86f82c1fb62399515846f832bdab207637652c57 GIT binary patch literal 2703 zcmchY&5jc>5QIH>0FGSX#Q&chAt87G#2xL4Tg$Oqnbz8F%l2e9Z;w4QL1Deo9`JIU zj3%F}y1G0FA)bnl+lXmv)sd&XRl5WbI7|T?`UxnbgXNvPbyf@;@r~nNqP7$g%84ZT zjL|DABkn2Xc$8O|c#0Z-7|I;4)}O_b<@smifH5D%Ru?L}&pnboca7Y>9sUA6w@aT<%6 ztgj&j@*X3UoePF<{Jh^?xow-AJgz&cEhp>`y;uy@+L0a35;q(1>{8_@lg0BpeFJ)m z5q*ZB_9%wWo$~OmN&lT*Aa_8Vk~xc>kE literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d8/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/d8/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..4190df794268dd2d2c1af6759817209cdc9ab688 GIT binary patch literal 181 zcmX|(K?(vf3;?q}z@M1n$p?sc@#L-4HY|arS&}TczZYEbI0G{i08DUBMxJ`vbd6Il zHd87u&$-lK9a*$du3eon2MNBV!*qa)+Kf~?FHX2J@(8j~IvUOFVH-Zkb+t;j#-aB3 iX*lkDH(khLgH%B08SZ_wWNv=Rt!2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/history.index new file mode 100644 index 0000000000000000000000000000000000000000..2c4adcd7713b58631aad95f05241c7b1041f6443 GIT binary patch literal 84 zcmZQ#U|?Wmkk&6sE!Hnf%qay@iAlxr@x>*TIjO~Z6}dSKOb;%|OHMt?ASkWXUGM&M cM&ks<=l}~w28IPoul}BbB+jvMqCH3)0D*uU@Bjb+ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/de/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..f87d659b6257e80d68445f5b6b199b34527c865c GIT binary patch literal 1178 zcmc(eu};M>3`L!8EX;`az9EH)4?yhbO>9+OVv40Ct{fN9zo*cOfrtT7)G10NU!QB= z7y!6{t5&eIuP%=B;m)P&C=~maBA5p5SbB>-(ooQjWGO33cF_vx#YSlsG@7xD>*n!txwh7P6*+!%u=PC>+13 zb$%4Vtli*x1aoU<=kRyN>x$8-u83x%9`zjb1rx4w_-JDGvwLQaYgYcvZlHwuH+F9} hLOE93odZv~--D%2f#>{8{qj#YGF&$)I>kMr_71XlknaEh literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/e/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/e/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..af1616f5427c16081e783b9279da2e3752e68796 GIT binary patch literal 247 zcmZ`zOA5j;5S{h_UO=zVNtL1p5ckrRyAqqB4&+lNiL|%3SaBh^dGH?ZR{%f(jS`CL zscoiMSuF!C=uP!7BUk(S&`ig=R{9>h&afjNadH;Q61IJCxHu)SK{kZcTOK2!HVJm; z;9T%GXD^0Rkgm@nB2 PNi(Q_Kj^(2@#o45sHawi literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/eb/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/eb/history.index new file mode 100644 index 0000000000000000000000000000000000000000..ce90f03f846bd204bab91ce709657190cc912e52 GIT binary patch literal 64 zcmZQ#U|?Wmkk>CtE!Hnf%qdMR)-5wM)K5$*j*l09nBk&j0`b literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/ee/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/ee/history.index new file mode 100644 index 0000000000000000000000000000000000000000..a65dcd3eb464026feccb8f1f075cb17d2e69dc48 GIT binary patch literal 219 zcmZQ#U|?Wkkk>CtE!Hnf%qdMR)-5wM(N9b&j*l1zlT}-lJldAoDixu(a!Q%|fo0$p#YFHbk zY E37#uy{r~^~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/fa/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/a0/fa/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..562a629e70993b0571e81916b6de6f8abb0b0170 GIT binary patch literal 242 zcmZ{eO$x#=5QV2bfEUm!bP`4M0ODS{au;GV#DV;jNh4Ftc-QA7cZS`(HAGB8XR*Z2RDHWV!fVPG8kR#gUB(pYoR_o(uk{JOTCoRI~s9 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/92/81/a/bd/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/92/81/a/bd/history.index new file mode 100644 index 0000000000000000000000000000000000000000..af6bddda5d24b39c657e4866124f0a5bdf12c46d GIT binary patch literal 102 zcmZQ#U|?WmaMjPrOe#t&s?;w@EiTbd&d=3POfJdH&r3=yD$YnP%E?d8*3Zl9~KOe&6#Psz+p%`4Wc$jxD3 eJRm;hzsg|-LCIaq*dn{ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/32/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/32/history.index new file mode 100644 index 0000000000000000000000000000000000000000..4e90aaba5a755ac8ee0cc8e047137ecb108dffc7 GIT binary patch literal 75 zcmZQ#U|?Wm(9+MzOe#t&s?;w^E!Hnf%qdMR)~(1%EJ{z+PfRL~k59?WP0cITtH{k^ fU=+MP<-f{d20_VP%h_ID=TZBxWumCJdkaRO(WWFD3^A~& H8oPl2pt(S` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/3c/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/3c/history.index new file mode 100644 index 0000000000000000000000000000000000000000..0ea5dbaedb01628e02e06a185f020f8bc7c8967f GIT binary patch literal 6435 zcmbVQxpEUh6qHRB5dnsPBI7EG0Bo)*Yz_l9n1Y1s1D4V5TH5kzXPI4@f`}^u0t_)# z7y?p*9TAx$Amj+BBH~KO41560&T6C?Y1>co5A;6u>(||*{!*zlQ93ph24%s-)gj?0 zL!Mw)SUL1}RlPVEV&%kfSlKD_H03oX;bGu8VNj{2PL+pzaAYu!Dy6h&AI)CVba37&JDRGG)GSR{X)1tgDjjoP`n zPuBqGI0ahsqq^e>9?Ll+CuWf!b~53j{hgxVl`s-N^xc#T#|x57ltmILqfd~lOyVGl ze39wf^Cww7%th^(tGs^}2<0U81IlUSWMc7n>mC95es~q$W8Re(_nm( za?ObpCXR`x2%e-oa9c;Jl%l3ql<)Du9($SDHZGHr2gq3tP?wZuN2;8$?d+dF0xXje z-%QI`1T|R&I-NX0iFv%6aqCfYU~`MwuNL2e!O57&s7R$%NhVUkq9m5y6{Q6gW$7L8 z*q3%UjPFhEHhK8<{S2uRHfb?*J+L_fFOsQF| zq;JKgK~f>d&I+sIFC zrLBI(KJ+ulLoYT#E8DN5818McrUzP!U4<6g-9yR?rUS3h8|=<=ZXSdg=_0DPg*>X5 zLu=!^fM9#cNK57x-LojyN%-b26W`^L^r%LpS@1W}Hjh$zY$+bN_S{YoH^W^(1I&-8 zdy_kCvY{WtW)ZoJlAUxw-OXfQ&0kWjzIqE$ONKy4YFR7Wf@13o#Vctc`FE6u979n< zb~AM?rl9quoJW_^n{&X2>R*()-Dr7v+y1j+Xsf9fu`-8(l9Y)e+O#CgM=v6_N#oF( zmKSbuZK-eub$4=^COrO6;~~N)A7kyt6htyD6W?l-iztSB`%lB%ryVx^D8 zpPQhf-J1Rf>cb@W@E>#CRsoxPTWOK;i+y3$~=YEe; zht#5>b$F;xP{Nb8WqFHQ@@z%CJdkaRODO%XfC^s`ONGZTHMd0=ntfl|}<>WID literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/54/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/54/history.index new file mode 100644 index 0000000000000000000000000000000000000000..1e60d84bda8bff27d037b092c9865ab336059a27 GIT binary patch literal 144 zcmZQ#U|?Wk(A3Y#Oe#t&s?;w^E!Hnf%qdMR)-5-&Fi0uTPfRL~k59_a&necc$jxD3 tWY{w0zsg|-LCIaq*-ks8;FQ{QlbCftkwkm9HKz{`O(X zx*soZ?HTUVwRdopgQ`>aqlS}=3FYUNJ)y?)vL^UnjGutZgok94rHm<=f_>ssk@SGsh zww2_%FUtQO0o-8ABOA9Md5Thkg`AZ4f+Sl7%2Mbd%89)kvt~j7u~M0~{0za(nu&?cT~n>WcbJ{lexI4q0(F>e+ki?vv|5rNL` zoVsV~tr^x<;|r0scEb@nh|L_0{q03L%%*z_Vx5(GH?&&)Id6;!^K4>J>ODY8Wb@rn z4^rAa4)%sUoWe6xZABNYUwGd%vQ~C=_@7!RC@~TXy9l~zG`FaE{-|h#X`W~nvzK21 z_RadA2B*3GAW^>kezknVXQQFzt%+Zikp`q}A-pvO2HWdaQa0LIG}>)Fv4#fm6e`I& zH-dvQ<>tK6$XMQ71JNWa$fejxQt3ky-bd1BC8~R;_SzW?i%{q69F0WF7S^-KP*|gC z&9PW6Eh%0^>q0kDv?rJm!}9K5$h+Bv*uW6Vs8*&DfuLY1jd(#ReHT%hwb!;#hc7;B z(d~4MQ+aVy!ec%kt%>6UD2~|+CzGbxcsd691>KbF-e3kQs%bDGvXhKD)G2fdccViq z3_ALqo&{OJipKP7y~j|FoJK9P?>rf{=D9A`CvcvOwD2bcFnf4d$xBt^(E6(o^?Ivs zB|ELZ3m+)P7WK-G)Hi4o>1~ao zX<$DcuRv(`f{ART7AAKPCT!Ppn9y|0=wa#o9fGAd4qC8K4)!Bd*dM?evZ%NkiHJ2U oYqzIAQ0(?E&?U?oi!m%q_g2qUl$mU*WsX(yUe__!KCtur15YSxs{jB1 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/62/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/62/history.index new file mode 100644 index 0000000000000000000000000000000000000000..e622f48b844437f06491d2457b50d941e0a4760a GIT binary patch literal 1641 zcmaKsJ5B>J5QaBMP|+YNdPKZl^y50aF0o*TE=6q zy4*`qsc(+l#*|R5aq`$TS4hpa2n7?DEtmEj^SVJmivuj}Zy)R0Izf!QVR5<&!WvoL zha*hrJ^?I7BswUOogFRv}s{TdT g-=WEP4;YUs>FBTJQ<&@1EjE3sPu1z?h=7d$2c$4>JOBUy literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/63/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/63/history.index new file mode 100644 index 0000000000000000000000000000000000000000..fc494ef6ecc90b251b3b5ef70b4cdb3f74c8321f GIT binary patch literal 345 zcmZQ#U|?Wju-DJYOe#t&s?;w^E!I!Y&&e;+PfRL~k1r_7%moU^m!wvd#HVByCnn{j z#^>kdRK{lj6~(6{7G>*Itw6|ac8ty=*(K(sv i86^<2196#cOqAJRmm(RLkcq>oM#LM3@OTgo#{mHLFMyo@ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/67/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/67/history.index new file mode 100644 index 0000000000000000000000000000000000000000..8ffac055b65514e3e33beadf000dded32bb87d3d GIT binary patch literal 88 zcmZQ#U|?WmFxSt?Oe#t&s?;w^E!IydN-R%I%1PBNGc?psOe&6#FDS}S2g(%3=ccA) rmgdH12rnc`3TNDFvCjh6Y9^6=nto w`iV)!@$o5{xv6=@dKI}j42&1-rupW^7woJ6QU}Rtb0APh5Q~&?~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/81/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/81/history.index new file mode 100644 index 0000000000000000000000000000000000000000..d22fe065460f0bae94e0187a921e22407703619a GIT binary patch literal 88 zcmZQ#U|?WmFxSt?Oe#t&s?;w^E!Hnf%qdMR*3C&QN>A0zO)1FKH8e0XsW3Az&`(S% sj*m~t%uUTJ)~m?PVPL#yH|4*|VFp3TUCY^CUguH!uw|mX1tS9k0K_~Uga7~l literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/82/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/82/history.index new file mode 100644 index 0000000000000000000000000000000000000000..32933512a3a0d3ddc00cd609780624c5bff2b1a7 GIT binary patch literal 6509 zcmbVQId9ZJ7~KR!fhdwdgJ{AbI&xJBS1w2pG(bgX?6tEo@y?jBHz5_*4Qo}e6R4L zURT(2wi9@#?o7L(-)lROWd(i|TdqIryPmM7dB82#7Bf9VJs~R<+Me84{CDC@q4V(j zm-~MIJaBUT-Qw_In}i-GfkVMd^3lkOydq~3biN*bxzlrX+ZUxt7D@ zn3wBcxb}FV@gEo_Uyu(()3)%eP(G6)2YzWf&bcWpKWYq3lkOL-vd1bJzG6LvR-`ZX z16G=?k#xk8j|z*tz$?a{YfbTDC6d2M@i}_et)<3{ z&}xZ7pE0RG`G}5eh_NsZ;D^ZKCE=M~G>Is(!!^Lj*=9g%yQpSI;Vz&iUL6UWD_&U%m$!~+}x~W^x8|a0mBx#gihrRL;crP7Ts=Pa;1`Yj=IHwo0q$MT0 zuG%&fubOIP6wA;i=LUdx{smOfjWoPV_eFC&M;RER%cRKjbXexXA{%|h$2~NXG|RPDO3H>py^YQk zT6Ah$(zwrsJoWWNq4V(;O?*>@n|y3Llt6{Id~xbtm1odHNYZq!HI5*COga!Io!rzp z=n5XXe2&TQ2F%MG+tBsr7rVCB>K?B7sAAx+qKTx1U0uiWhLiun@YW9G*z`uo?L)$2 z{cWN^OY?5*WL+o5aX5xnGCf1G@GM*Hyc;%Ae4{yn+Rzte`Mt$%c3bfe8r2bi6F-sr?fBqG}A ztNx$>4SQ%ud7Zv4>Z7RM*Vkw-(I=7N@wzYM`=b+iJ>ATz6&t6hLG%xF7t!Aq6(s>@ zrAAdhN5P23tyY~MayrxBP`$K!Y3^ctJu~>&Kn~yH)rDUeKwn+x$hd9s>1;MST2{dY F{U3aCjH3Vm literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/93/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/93/history.index new file mode 100644 index 0000000000000000000000000000000000000000..0e70862bf5c2211e2e0f303b613d7c5b358b0cfe GIT binary patch literal 75 zcmZQ#U|?Wm(9+MzOe#t&s?;w^E!Hnf%qdMR)-5+SGe{}WPfRL~k59?WP0cITtH{k^ fVEoiG<-f{d20_VP%h_ID=TZBxWum%)>O?iOB6aYUpGuQwC literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d6/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d6/history.index new file mode 100644 index 0000000000000000000000000000000000000000..aaf635ffa9f15a85b393171e5911eafa3873a166 GIT binary patch literal 1713 zcmb7_J5Iwu5QZI!R5Ub5bRZ!LAaPzo6o~f$c=gNLUXfMS9<#ei$T0$k-~tqgmP1fd z({Tf^y$)FtPXY(LVe94A|91QQ?Gg# z3a7L-y#HE%b(U6M9?KtZiyNO$!-L&Y0&4vcli_-t^$oA~jPR-`FW^+b4bfZ+M%p02 zkWSwJO;WyOEV6nU(skvbxMKs&l#Z&$^?>+o0L3I3H$1{}ZKAY1m*Qb8n91Z}nee#_ zt~3c*)FoWAFiFPzjt6&!cZ#K&-EpKtHv1H7XmxChJM%hPjzN#fL_b5MSl>z!QMHp# z!S4_i^C(KjKaM7^kY(13K$-UwgOfDixnmb)1lB}hdBG3@MtqUDVP!kSmVo18h`X`1 zRdcUqW|vsH8k%mRD)%8WtTT*-`!;I&W1O9>ff?eW*=(MTYGSB;6!q(%NG{sw?$gzn z(lO@B9!gF_P8~kU#yWQJ7~AvqOm1>)nKsD-Z1T0R=7ncAbrgYwIDmd+8F-5|#-D)+ XW$ewIW75p+nf_zi5axSWMSe2hWZ8p` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d8/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/d8/history.index new file mode 100644 index 0000000000000000000000000000000000000000..f39f74335b9a426433878f6eb88d00c818952ce6 GIT binary patch literal 90 zcmZQ#U|?Wmu+-1VOe#t&s?;w^E!NLTtjsSh(alLLN>9~KOe&6#PfRY!%+HI@%}+^< uPtM6NPL0njNzK)($jxD3EDo9cU*#}^pyaOQY%j0#sD0Qn(cXfQfdK$m<{$R} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/de/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/de/history.index new file mode 100644 index 0000000000000000000000000000000000000000..ae135725d160a7f000c2aedb961ed1b32776efd6 GIT binary patch literal 568 zcmZQ#U|`^6P}a}MOe#t&s?;w^E!Hnf%qay@iAlxr@x>*TIjO~Z6}dSKj2k{o{;zVF zK~Qqna<-S(dDK2^nP_jp2s8k<_LR)r)I6y6MJI7+SHWX@QD$B`RR0oO`f*!dl98GV zbNxorU7wtvmzJ3h@%%zuwkzRueNujY4%F?F7UA%_0#4nTDNwzONw+z%q@)O{dm=8I Rafe!Reoj72`vM%60{|1S)H478 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/e/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/e/history.index new file mode 100644 index 0000000000000000000000000000000000000000..5b57f0a628416d82fa92c72179892df152cee16b GIT binary patch literal 93 zcmZQ#U|?Wmu+h)SOe#t&s?;w^E!Hnf%qdMR*3C&QN>2rnc`3RXDFvCjh6Y9^6=nto w`iV)!@$o5{xv6=@dKI}j42*}wr~Fqr%pfSaYdPD?>pW^7woJ6QU}Rtb09v6R8UO$Q literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/eb/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/eb/history.index new file mode 100644 index 0000000000000000000000000000000000000000..caa552d87217fc2f3317353340fda05166d6db0a GIT binary patch literal 72 zcmZQ#U|?WmP}k4NOe#t&s?;w^E!Hnf%qdMR)-5wM)K5$*j*l^yq~^km_=v*@00bp5*Z=?k literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/f6/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/a0/f6/history.index new file mode 100644 index 0000000000000000000000000000000000000000..0469d6c4d5805366f17e1e086c549d26cfe872db GIT binary patch literal 168 zcmZQ#U|?WkFx1bA0zNGZtFH8e0XsW3Az&`(S% sj*m~t%uUTJ)~m?PVPHHcKIOm4VFp3TUCY^CUguH!uw|mX1tS9k0KO<4NB{r; literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/21/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/21/history.index new file mode 100644 index 0000000000000000000000000000000000000000..f138d0b0b9052318057d49f679d0f1b88c3774cd GIT binary patch literal 836 zcmZQ#U|`^6FxAh=Oe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJKPb?_VcLa+% zB^K#rC6*;JFe)-l{jYMEK~Qqna<-S(dDK2^nP_jp2sF}*NCShRrn^=YB<7_gCgr61 zWEPiztSQSZsf5~Mq=~~88xn0nGuHr@xeg?ni^a{30XW?3M55U)nTa|1>25`d>A9(S zCD0Htq^8T!%yz=%a#BMZ&0J$#ZgwFtL}2Ek#ij!;ce{~jen3%bT53^hUUDj$4bC`h F003G|G)({i literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/a5/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/a5/history.index new file mode 100644 index 0000000000000000000000000000000000000000..75f14384c8476ad92458119a6ab448db20bf3bda GIT binary patch literal 671 zcmZQ#U|`^2FxAh=Oe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJKFUw3V*Y{1$ zEA=c%&DG0FEK6iyEHaz%U*#}^pyaOQY%j0#sD0Qn(cXd)Xrwu@20DW6@y$<3g&LW_ zkHbh4VvP(gO#(R+YF;reCpr;po^yUqPGUiEW>QWn#I<3-kbs(=gv+(o#F`E6y=v?rlc0>WhIs+GB7s9&iJo#m_bl-*K)R(*Ll=FY?)|p!3Z>;1k*tV pmt~ezI%nkP7pE45Wu}%xO>e|yx-;=^M>E|wKP5E>YJ39@;{hYoYQz8l literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/84/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/84/history.index new file mode 100644 index 0000000000000000000000000000000000000000..230fa171ee357420ead4856853c46637de798419 GIT binary patch literal 1521 zcmb`HJxT;Y5Jr0qj5H7b)>CH2&mM7Ql0u-LmG{D2~apivOYc2#ziCt zRy*U++YDSr-ef_8GdcXe*6Y?o+`{sNAjclYDJUk2M9f56ip@th+b$`E&w0j9Cx)|xk;jOKw1v=8JsHhbs_@86QmC+#D{{?s=U7H?mwbT~%W;RoMzy}!%=4DZ zR%lnM3QhW6a=wX-Z!^$s6CygKZU#klzUm4WT!n>{$9J&ZVd9`d9d1Id9j};#e*imo BMvnjh literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/84/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/84/history.index new file mode 100644 index 0000000000000000000000000000000000000000..83afe66b9351b1ddc41f18c2c9aff06754be9122 GIT binary patch literal 126 zcmZQ#U|?Wmh}F-@Oe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJK&&(@HEy_#G z(a+1wOU=(oNz6+r%Fj$G)-TIUE!R)X%gjv#Y0-BCv+|1qit;Ne^|BJn5*Zj5SWWw{ Za+pC-a@TUUm)CjJK5Ut2Z^6jG000e(E?WQq literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/a5/history.index new file mode 100644 index 0000000000000000000000000000000000000000..4c0cdac06e1b44606664a4f9a607dc31f3f4a587 GIT binary patch literal 116 zcmZQ#U|?Wm2-eTZOe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJK&&(@HEy_#G z(a+1wOU=(oNz6+r%Fj$G)-TIUE!X!03Wfn0?nU{f1$tSDWr+-olZB`KS2@feD7kAn S+so@bY9F>tw6|bnU;qF)vnm4s literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/bc/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/19/bc/history.index new file mode 100644 index 0000000000000000000000000000000000000000..55b1f98e85bb788534ea503bc43e76be880ff180 GIT binary patch literal 360 zcmZQ#U|?WoNYKy8Oe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJK&&(@HEy_#G z(a+1wOU=(oNz6+r%Fj$G)-TUYNlz`&_X7%h!?o<^(4f<>%ytWu}(vWhIs+ zGB9pPoc3SkFoU4vuH|emuk)yV*fP=Hf)QwYIF;;nD@x2w^+~MEFD-#uxzGxSl@V03 Q(g*0}#3B?sH{$Rn0JAcO{r~^~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/21/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/21/history.index new file mode 100644 index 0000000000000000000000000000000000000000..09fc0fdd4f8113b20efc94dab5642828f7ba9f97 GIT binary patch literal 196 zcmZQ#U|?WkaMI7oOe#t&s?;woO4d)#&(%*%F3HT#OG+#%&PXlF$xqJK&&(@HEy_#G z(N8QW(02q&J0%u*<`(4WWhIs+GB5_0PyMfQm_bl-*K)R(*Ll=FY?)|p!3Z?pm2A_) Qi-4A;7C|jYn1|g00J-l+hX4Qo literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/a5/5f/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/e4/81/a/bd/a5/5f/history.index new file mode 100644 index 0000000000000000000000000000000000000000..07089e27e4d1de1df69401bcee07a9baba180779 GIT binary patch literal 1812 zcmcJPJud`77{_N%qEfi)bPANF)rk|_vMZNJsAtzChS`_Q?4I}-8a{$jqtf~UUJ_b# zx}z6%F2n9#Jk7IFZTI~4|28c`NQbyoia;@SLbVEMm_(F?nMmS*DSg0|Ou{27;*6`9 zNjebxm_|I#=}sQ_#dlA!H05gXkPR4dX7%~k+zn~ZTwhGSJxwhPuTGbjoC1S{tc?D| zaNLYX7IJra_BUh|r^KA!Ep*xQ(;lE<9e=)?3%UR6((n@y(8Ck@ife9CvMMI#0Tml~ zhRMK>0JU}#M>4JLCuyGcxGV?Q zf=u&qlv0lgzhc}yBxef;@`TQQc3#1}Lir#|U|+5J9y|ZA`1-rph6o^w@N(ZWw`jyoNKZ?6G}aZh`)O18G*PPVAcr^pUQ)k%9mr|^((fzHvm(GC>ic@U*LZJ&N*HRf?zf1F)305X3nh1Sf+0nWKL+6g0W+6q|PQxD94Qg z$!21dbH`3I8ylS)Zfyi+`xUHPwe{EM<*$#Gt?!qI_Cd=t+BCwY;Is1d z5IaqLd^m!_8`TJ%H{|hWgvWQF5Duic7b=gY&S_P8>^~ut0f92ijF!?P5=c8*IS{I$ zlwhG96JWmazP}Hq4|6?rrB4@2?Sy~`QyVUp=O)IlL!O!34p4Qzk%^PSLq>}S2@feD7kAn+so@bY9F>tw6|bnU;qF-mmdBA literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/bb/history.index new file mode 100644 index 0000000000000000000000000000000000000000..59a476d75cb7fa41cc4170896596aaca7051c849 GIT binary patch literal 206 zcmZQ#U|?WjkkQY{Oe#t&s?>MPODW3FOz}<3%S=lxF43#V&0%0P_|oxTyILW*+8|d)7hhMs+!O{z2VAP9;i?OY^0QKt UOZ0$rL26M+W@<45qZ1Bo00ApT!~g&Q literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/21/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/21/history.index new file mode 100644 index 0000000000000000000000000000000000000000..74a798760e78a5cc4d0c745cfc87470860541a2a GIT binary patch literal 897 zcmZQ#U|?Wnu+T3qO4d)#&(%*%F3HT#OG+#%&PXlF$xqJKPb?_V4~BAlGK)(bfhx)} zODgrU63Y@9m>d4z?9w~TASk(OIor$YJZc)he%V_vGB7;2o9r)&B)($SL9qA&udF^E zB=HYhCW6HoY>0G&TTxT9SPfJcp|$)W5Z^!eG^v6=5ryr z!(k0X+@YL14_Ulp0YtpuNMR1LINaTKM7lemC^ap$C^auR6)gk{SZn%_UEU!28|=ah za@--vE|=H@3BiDqCnsVJK_?~d z*$~$x`1iGAb&Uy;u0ahAt^-@nHo73i%Mb1a4xsd8Fz;bKvb!8AA?{LO`e2RhE`g3G z;L!Wtd|MlLlW0GcoY%~f{P7!k;Gptgoq!= goUV;5-Vm}0Vz19fOXPI2!3QEn=#GT0i^ywOYAE}B=H^Aj9~E(FYY^wA&E=q zK*S&HYH>ssUm*e!56HT1i!3hiTN-RrcU~#Bf`)%S;20>}9?t1s9Ga3c%xdm7-GB9kY;d_ECZt>-? zJxE+(Nx>_g!wiCwyOy)Pyw0Omv3?a;d_%YxKPQs-hb&-g@K0w@Z;oR4k$Zmnz2>=$uXzl<2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.indexes/e4/81/a/bd/history.index new file mode 100644 index 0000000000000000000000000000000000000000..1c8941b81de49cecb828d9e84838ebf0a35d8666 GIT binary patch literal 297 zcmZQ#U|?Wou+T3qO4d)#&(%*%F3HT#OG+#%&PXlF$xqJK&&(@HEy_#G(GN;3&Mz%W zPAzuM&n-wS(aTCKOJraaxKRFz=P-kyF5kk77_!|S`yg&y)ymHs(&yNz7EsJEks zSCI=Fk8MO($KL0C)tBRI(VfT1weWBrIxA@5^+K?&Z4Jynw55r=Pp_HKm27hPPGcUr z9PsdZt+FK*J={dDRyOOLoPsb**Acsxf=WZ2aFT2D~=}mZLyECc5L{% zYVqjex3wkc!sJ)n9dA#pL+?^=QTEcCfNa;ee04BgXt zl5%#|v^@!Z*-#I6#c+KWdT)T7eKz|ny7LExu3oRc7+pR@F0DLjL>DD;*>)}mz3|r) zG|x;$8ag|3n7i-BWoCvs3rpYRE{_e2t^*%3w{nk|o<4(5D*Aw)vN*jEME5-0&+EnQ zx2Ex__0EtBhs)#WOl_q4(}OqAqec6;`&NhcpvTv{sowCQ1igD|FL%Lstq8sFn8aPN zU-~8=&ei=IxiLLBimqL#=k?mTLvNuQhPRMkmz}F1C-f4zb$RCwbiw}&uebhjw*Xyi zCJ$-n^U=HO$ywlM6MA$l`GE7p$QT|2AjvgB%*Q(E2(A87q#_?)1`ka)^ zd8gHc9@|WAEkBZr9-dm@D@`!{D4>f`a;g2*W$5Zz@<@4oD!NkkC(ltwy&LrKedHW+ z@s%U%(Iflksc$fmiQYX+e+AaGrAyEw_sCgu?gFlM_S-D2WXpf7{SlEFIE9a7nIH zDoqGI1YrY;1AZ_RrEM7o7elDlQg4}7pMZ9&-{90z?id2K@OlRIOf9(wTv&~Jp}0^P ziJpD2enFK;!Ps}oa+(1d)^E?O&}vW78~~+exi|L;a3iflqILbC^!W`m)b&v0F$r5X bsrXb#68ZZ^&EcwM+p!AW%h+9c28pIWY)s60 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers new file mode 100644 index 0000000000000000000000000000000000000000..ac1cbe418bd9db5fff8d39af0c1ecb00fcbdf62f GIT binary patch literal 16174 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 EKke`f+5i9m literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers.snap b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.markers.snap new file mode 100644 index 0000000000000000000000000000000000000000..a8c6b6fd9a193a5f737702651f933e04b7ef7fae GIT binary patch literal 53153 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.syncinfo.snap b/.metadata/.plugins/org.eclipse.core.resources/.projects/ActionBarSherlockSlidingMenu/.syncinfo.snap new file mode 100644 index 0000000000000000000000000000000000000000..c8b1e33aa6d6ef0d9dc74bdff2d7f499f42c3fe8 GIT binary patch literal 144 bcmZ?R*xjhShe1S2b=vdAllRFv3@{%684^6N literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/history.index new file mode 100644 index 0000000000000000000000000000000000000000..4fb166e15e37c51a28c043b8a38dd62b8011f2d1 GIT binary patch literal 99 zcmZQ#U|?Wm5YjJ7E!NLX%`4Tbfh?X71`!7U*4G|` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/5f/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..d717bae325faccab2bae2ef3a88375cc5d3fe91a GIT binary patch literal 213 zcmZ{eK?(vf3`H|@02glc45>R0AnwJLyP>pU2sFu%w&2`eaKwe+@_+d6zX1RS*axQ? zgtP~VtoW1y;|Pajf>E;@XXH#ssqj(>V{UM~n26~^$~AK{pHg=xZPOBGg5fm6*?j&^ qIwNZ%*I3YL=GuJ4J5}qRXd~P|HSD&0b6d#U3gMpzy`L-osJsAdXG-A! literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/d6/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/d6/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..da02bade374322ec7c72890dabcf2709d453d8f8 GIT binary patch literal 247 zcmbu3F$w}P5Je|@04u%51Z+Hj*vnS7AsLo|OlFy6!Q6huh=r}?|L`8q0l)-DZ&ZB_ zUAN{XaKWc!a1&hA7NnSYt%MsRmqu1XMx%vmvyL-W-7L~AaZ{T=Hyp;ko33Q7gO4g0 hN;2hyoaig1H&^khB3d4j2MDL%r1NNUuVDCFzXO(ARo(yq literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/de/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/a0/de/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..f9be173b93cc2a7ef34c4eb7bda3f1bb512e6686 GIT binary patch literal 314 zcmbu4K?(vf3`Ns9fJPeRoEkYLUNJELTG)3-BD7Kd`a=-xr$z0Q>9$5qYVUR z-@!pNyd#Z~b0y6-qEg^eb;5y)GKyAnX literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/e4/81/73/96/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/e4/81/73/96/history.index new file mode 100644 index 0000000000000000000000000000000000000000..e0bf4ecca06d0a1174008ebe97320eca7610d637 GIT binary patch literal 1642 zcmY+^Ye-XJ9LMozhB+$jjKWOKR+hKGtt6Dnnlo`|+PVlDUbakf=5#eTS4tiWGB3z7 zGhc*Fx=7AyDwaydz_b#D8J3o}qZLijTqS9ml6#)L`1k6-hcCbLoWtSRA%s|HH&1yX znU|a?=PA==XJi>?A%5xnbeI|A5{+NZb%FnT5`ML|jsJZwh*>nz&AT=L>X6 zq;20#Is%<`xAl)vKlFJvacX>fA9TUe3_hoEpyVBN^B8eS>O>E8O_$AU8oHpf8;Mhe z)1A=yam48aX$y2s6mh2M>2v5l4z_(&RULH2;&*&bi)^PJdUGd(-L&ZlJqO-13h2SE zT{>`e7P!cpxFU|uhc0>8jeFhaXL9HRWyB3Hea=A_=Mkq42c|+dWD;jiUQ2-<+ma-< zekYRB;U~9N&g14+oEQGJGT-!oxN$DD4!YUlDDIhR56_#R*Jegz=T5#@`=2jIVmHz1 zx-!r!7Vbw`?`yp4N9_X6loJ=XRUqi1Q^dJS!<--JuNPO7o$#?{FN3j+F01 ztnY!_+P*iT9dTTn>vJ~b1r{3joyShK>C&QCd~<8f>WTh!UY0$?ElFuI===^y*?3Dh>?O@Prrik-P*%iI6Nu_v3!+ GbNvH5esp#K literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.indexes/history.index new file mode 100644 index 0000000000000000000000000000000000000000..beb2feaa005155b69a6adc7b1d132ed085c8c984 GIT binary patch literal 245 zcmZQ#U|?Wm5YczcODW3FOz}<3%S=lxF43#V&0*j?aKGu~q@xUi(pug1?oVelW-v^2 zuwZ0hPzZTvtaF$_P;%FDwwKp=)NU;32a7lO@cz?A5-*5@h))p8`+_W43Fg-+F=UGtV~=q zX?o6SzwW#WTf8OqUwNlXOTi6tF5vYK0H&$SEaU-DQAk2r zgl;0|lGp-#(xBwcPlYp?5OGb}jXaYV{4)FZDZAE#;b8ARgXo(uS!er@*+^cFh&z zszAw8)2u6r;yF0~N$8FgfFA1acY@b0397_U5otuMl}ZScn#WA*fu3n@SU{T_-DPp2 c#~7}pKuPm{|9JRuz+2JMhX3&^Q?n$KUjxw2C;$Ke literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.markers b/.metadata/.plugins/org.eclipse.core.resources/.projects/example/.markers new file mode 100644 index 0000000000000000000000000000000000000000..52629ad2a0c4bb89ee829cadb3295330bb116364 GIT binary patch literal 863 zcmaKq&uSYn5XQ&5l*GO#P$)%^L()U!rl;1_2Pa;rgJS|Uy@X<9X}VUTl@|S3V)_*A zv-H-7>8*W@YB$9!+q425H1jdv%ufRVDZCltJu6CuLudJrn_}pc6jJ8}>afdY51I-0 zvXXvFZ&}3vAc;4g!!HR?V{?jJ$e!JR6$K;m>g*#qB}QLFrN@)=poPL0@U(6HV9Sj~Dn$wh?cA;{7(N=N zLDI{~hsi3NXII%`xq3HQOy}8ZHceqRZgF}WInfp;`X~3f(|9xfO(zI_zG3#gXVyo4 z$qzVryqRVO7hH*2TpK0%w#J>npoXys#TsoLIDoynUZzESrBC4aKh>mmo+))#C7&Ah4gGx z!GOp0$&KC4YG!cX`H`Q0Bi?sdp^ckg>w9hD$uHPMba! z2>J(l=q(6(D?$hg0w3(9m%x`uda(z4>!sPflx;OZGP$nVhl82Tc~}VC5{l5E6%I?RqEH(Mn<;1t?Q>o@+gMYBJP;PoIqW3fXo1eu*mL08;jD}pry`wJB;P*=gV z`!^9Wlbct-nJhk^S-SdtBcj`djk}94ZoV1%TlCY|)Y#l3HX~v{+tWti4Zt>G$!v)bxwe09yU( zR{c6u3a9>3FYDX?!S9lK`MP83<L4Q;u$UbJN;_ Hk%0jKZ|o4y literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/61/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/61/history.index new file mode 100644 index 0000000000000000000000000000000000000000..7d3141d4de6f3fe09bb3aa8df7a9f74dd4d312af GIT binary patch literal 397 zcmZQ#U|?WlP|+_+E!IydN-R%I%1PDDO)1FK&rFWbP0cHfFV09TO4TdKOJ`tY_!4Fr zbeKUsdm4ARrx% GH534!^NU{q literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/62/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/62/history.index new file mode 100644 index 0000000000000000000000000000000000000000..a60a002b9213c4f461fd6f2d0f405c5619245f6e GIT binary patch literal 276 zcmZQ#U|?Wj(AO_YE!IydN-R%I%1PBvOfJdH&r3=yicikZEl4bh&n!vJjZe!@E-g+? z(W}VKVPJf)cavt&VFp3TUCY^CUguHU@aCqq1tZWfDO971Q*%<2OY(~#x)OM`c|(A@ uL@!+lc@Q||s08B_N3bq+R9#pd05QVAXE}C@iSk1M(4TNW6s*~Z)hGZ}A!5D& literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/82/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/82/history.index new file mode 100644 index 0000000000000000000000000000000000000000..02d7780d6257167f691d8903c6e7f43538792fe8 GIT binary patch literal 338 zcmZQ#U|?Wn(9kbRE!IydN-R%I%1PC&$Ve&3)Xz+gPfRY!%+HH2PE9OI&d@8!OJ`s_ zU~$_f=rDtzE!NLTtjsSh(J#))Ov%hk&rQuM%}vbA%gHP*(W}VKVPL%ATz2`# zQ3gS=&VQ@SU#u2+VD>V|f)Qwd2(os#dM1a&g8j(qIqtpytN$Q-Y&Wua$2^EQg95TS ziOD6I`FTl+Me)h`xdn+(Hz=HzhzL5&ASk(OIor$YJZc->+_VO}K^|Eznis&%XPvNl z*BxYQ3+6zazu~p!O=NL}7>IKwY!Y69EWSe$>U@=ydC1}~raT9G>%t+vE@W|-(*VCN BjnV)B literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/d6/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/d6/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..2b69fdfcb34e389ea4a535a06ca1d1133bd23bad GIT binary patch literal 751 zcmb`FK}*9x5QQgI@#e{!q6IH{*(gN|y%iBJqD4V_D{C^uf!&=jJJH5pZ`z0kp$D~l znq8QA-`h6{0BpihDi~8|Ypyhnj&cfx$544o!BJE*_YO9Cu$QqnHsr#T8_LmO=BSKl zY_70>$=-9AdUutRvdpqd1cS~>TOcH7Nh8&Wy)%2*J~bDE!SK8XLzd!eOhtx*q6F)V zV9_W`ZSFC0B^kC;??0bmr@c>vOBAgkUB!k=nrMFD!EV>|x62muFJ=~<$^W?yx?G(w zgx{7qBx}++T%ofFy$$>~U$GU{D#CPNh7|fwkJsb=@h#4)*uM*SGMcccSkh5*0&Ae+ frKuN@bsQQ;&&HOed1zPgrdfb-ru0f$ugCNU0rvX2 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/de/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/a0/de/history.index new file mode 100644 index 0000000000000000000000000000000000000000..a3c69a4dd5e74582fd7be5350a6693817f737e89 GIT binary patch literal 639 zcmZQ#U|?Wp5Y{hBE!Hnf%qay@nJLA36}dSKj0tn(@`4UC2uki+&i3*;kJ^SeH?1ug zff_`Sm1m^p{*#9;QCu6l5MMp|zZfYLXu@jP(&m*j(xTG>C z6{3T4!=WY@Gc>(4BfX ti%#E4W8`9_#V1snxSFmwP?e^EwuRvn!*268m6_C5aQ`^y{ao<}+_bh}WMBXQkm(%T literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/1d/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/1d/history.index new file mode 100644 index 0000000000000000000000000000000000000000..6a01a682de78a3010d6073f1e9e6dc6e9ddf856e GIT binary patch literal 381 zcmZQ#U|?Wju+%RuO4d)#&($x^$xO-2OV3TsE7i}*OwvzGF3HT#OG+%#cLcMX5{p2L zvdof7y{yEtLw!e0B2v*iHOuOcroCU|s%axA?piaK+q~P%6f&}8KXZlyL2b>*XFZ_jVSujmi|{c!mHe&?L~yC;|sGL|f5 zY*rnk%Qi7KqhXi9yxXKV?`4dJos5>}nN+YfR_(CoB5I=t|D&_IGK9%0Cw^*;PIo`%*ZB^v^G6#Bt%hr*M=LA=Cnd%On(%1(f@+F zkdUzuyZtb@>dLL@*gb{dq~ow0J0AkhUp_wuyLae0%@-#|24T;853U;D^J4%VxUU&p z>6rTsyQ~6S5meEK-CF=oSZ5FRyn!dQF4t{vV7HfptFmSt!0uWPt~_hB{Ljhq(Od*; z)o19fdb3VHawTvb!O9&WrTu7|ttCxx9q#SN{^ulSH0Ay-GM~KMW5H)EX1|0pxV1ow zozs9TqMNp3_shYZGh0%zdj{d#5rl3vc4s;`Ke%NvcEt*CHoYkpJD>iT_CqSAWq8vr z#TIsWI5WyX?$k>dw@{0VT?@ z7lYS_#C^stww;5VNsrYu)^nfAA?N(1jo4jv0q+%8 zVwbLhv+?pI?A*lDG>6#3uZ83Ml2g>3+x+F&HOs(BZC)vM<&1zA3?0E<)q0ZV@MZT8 zVV6X3L9IK8{leQ^=;v3_c>EL1yaQh4uM5VmDhC&;lYY!Y{d*kX?5fNm?8NpgarpZr zqxu7H8vwwHF0m ME$)K}ySo7VH`nR=i2wiq literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/e4/81/73/85/history.index new file mode 100644 index 0000000000000000000000000000000000000000..0094b8989d09d48c428a39cfbc1b2608a035f90d GIT binary patch literal 3106 zcmZ|Re^AqP7zgmLA|9IA6b?cBF->r+6NXyii8?gTK@w8|XNrs;3uf+z+r*h1OhuZA z@+HymLYG#TAKoZP(f zZ~{6%l$=xaIa71jSZyYQI=4_~NiN7W+jJJ1t$t#`x#-PjxM7he4-dS1ZAgs!{`DC> zv&F^snYEbawP#EzWP)-o7xW5zaK!C{baASwcjVyy)8w9Y4iQ}v9`NMMv*`ZR11v{j zR3Aq74c^Dx^I4t@o$uaD^%>C<(9QBa%+>WmS1k0yS+6Gde5|DW>BQyD+^~_yKVKhO zHf>8?cN=q8YgiPzwZo1Jqub1Vh3)}ahD^3O6khK@RuAJOaYTb!$e~sKNUfF`) z5J#>w>~y00$CG>RX)4eiF9dw~jg9E4(`Q+q{3lIo(Zy17&(k9YbmyHGRxdf1l!fm5 zmfVvh&p=ms$rT%{3(@_J6~@S{PCpWXkzkHS&7owuu|(smbE6vL)Ft)%?B7?3R=_uPs9F>>@Xt&a2U-R|55~=A@(7ogx=nG8dq`)*I

F5oOsVqnF<;PAHpcgeNSdQo$Q}a6HbUp}UE~%QA zsRY+nhBD_h(PPm=OyusuK~dk!-BV2NFL~lc=S~)~dPTSROElytmy^2{>#n0m zOea^LK6|B?&wiWbxQ|4Bitf6qqkg(8_w@3DeCE>BidpEY^gQNf`%7WyoFRw&z|4aa zpwEywbX&I%oS5djvfuJ2qTxCc@Tx(uxS#j=i>TYa{q7L qIl3afv4A#Qkfe5AuQi%@DTS?3@sV@{{*&dZr}e5eEbu*Vz5WBX6HFTb literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/history.index b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.indexes/history.index new file mode 100644 index 0000000000000000000000000000000000000000..f35cfab9828ebbcf3b9e191120ba81bf92ad4ffa GIT binary patch literal 77 zcmZQ#U|?Wm5YczcODW3FOz}<3%S=lxF43#V&0%0-@OUBl<0ylmSm(c0<}X%@Fce>P gv|walaJc$GCgd=Kpy;J5ArAtl9NqBdrZq?$0JO4k#0zTtr}Kv}dTn4jKOd^4+^?ryoW^ z`Uw`)GL5vZ6SJ;FT`baEGM^c%+%I-@TOH{qv;WdNQ&7wW?0xzHi*jH{b_cg-tFCm7jp$FXPFR=d2Ji?-eoNx=w!^6sG>8S=cL7+Ew zf?A-SlH@uDL(OF&z>#;!mZtDsH^1xkMBbI5n$$^L(G}=Ig>`o%I^WqIZoO}FteKbp zI#Nty2F^b-K4ViLt1jqaYGY_Njo9L1+H-7Ie(Ow=h}`{fs{yE&e?w|$& z0HpX2|BQdCfM+PHsaP|J?O=6BcU6rttlErj8Q26lpb%X-1HdZCn%Hqr4X43ewT@u} z86Jjo8@haBn_xqS^2y9qj4%R^qv6{y*T_+9BpDl29RbW>+yUN*B zX}C#YIB-HkF0N6wzpN`f$R5aPb;LGZ#9Y3ez6(wm#KLQyxrLd3z;j^K!41r~1Aj9G zvi|WU%m3^2kNivOF%2*4X^_6MP~``_vQeG*2F%1t?m+rUyK*!91pG6uwJo<5^7AYU z3Jbo%wzW41Zk8GKY;^_gQ_tN%44IC)xV*CR&PK6PTC4ip0Md(!rmJ9Q+gG01u;s^vAM;$Xn>k z7zf)!>EP=`4!#X_Fde&$^j6C5D&j9w{4-t~Msv!ZZ0;#8Cu{*$ZiSee?Kr3prGw8C zIru8n!EEg8nfDx*n*Q4VI<6B-@6MseJN}Ge^mka0{EZw&%%Q_lh`&n5fjN{8%849Q zLL6*%99RlCb!55cB4-zj3iU~*y1ua9s{J5H{QyR7Mrf~i>MORU7A3}1MXau-t^}aQ zcooP>I&l%NG5yQJtF7|2E+lR3>7zO2(?AEiP;1R}sCx{#gjy4WAxD zq8&s$*+SeXE-Wmsl?TM4rzNcPeG!XJCB(WO#7b}-oo8j5KSUa5A|VY6(p>N*6<|@< zA+N<9egUx#9nZEYb737bUJ_FVU4|@&|6=kl{i4=U2fNB2{w)Q_d?E(;XgXm4Cm7&T zJHTe0dc5Cp>+P-vLx-A}Z&@{nws;BO>WOSr^LJ>}auM%E*sFu3xP3!PF@nVux9=uQ zLHraTStA#Cp3JYW@>Zl+U9W^Ta=a5cs*#h2n(PfFcOp^~H}ab#0-WQ~!)l0;zXD#` z%Sw0s--+;WDWsv5;Z?I_`D>OQY9T+Mh3-Hx4swrV2UjB;`cn?WVmqGulJ;W_75X>A0!U8fozRBm0CT5L}E9m^~dbH+DM~ zJkf$QH`IUyX>J&HXza{P!LVcILQ{V9WX2+*G@lQNVsxT3juVBDs3?TQMR`-YDw&f} zQQnG)(iEc%%R8ip_az6}a)g72KgBrM8%hU1Cvxy>jDvmOL8`APPEgvZ^Ab$zmRM7$ z{^jX^0eWnuF^JY2H5;&7Bt{nvoAgnmaEiq`48K`EUD#dpD&3kG&`cxc6Pc05^jH{)ax{ SK}JfE?fa+3gVzR3Vg3t5YCJIj literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.markers.snap b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.markers.snap new file mode 100644 index 0000000000000000000000000000000000000000..25adb00d0d0f16140f7ab11c60d176deb06e622b GIT binary patch literal 38432 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 BC#(Pf literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.syncinfo.snap b/.metadata/.plugins/org.eclipse.core.resources/.projects/library/.syncinfo.snap new file mode 100644 index 0000000000000000000000000000000000000000..c8b1e33aa6d6ef0d9dc74bdff2d7f499f42c3fe8 GIT binary patch literal 144 bcmZ?R*xjhShe1S2b=vdAllRFv3@{%684^6N literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version new file mode 100644 index 000000000..25cb955ba --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..69385c20159cd3c56affad177b5f16b191d3a2e6 GIT binary patch literal 245 zcmYk$L2Cjr6a?Uxr6<9I(q7u%V1kh?OK+ujFG}w*88vp3x4dM*{(G%R@%#-lqlie6 zGW68Yo9Com4#F|$7@*<%I233XDoyV2IYhGi*yF<-Il-JDNWbQ;ixPeoeaz$81op)U z_E*my4ZX4){u@0Dw4m@P9))I}b49LS&L6Rw}6%q5L9;i6DnmLci|X}Ar0IT?dfav^FE{bU6>^3#$lIYNCtBP~?A zI97RqW&c80;8Fkaqru>9|FFLU2KTzXEc-~6CdM-t?sjXdKEd0XW)){={u_T1jDs+U zUQb^7(aAWNoSwMw^||1QMqPWcH&Z#q-kdb$b?m)YdSMDoZR%X`jLT_AvRVr^dLP7I z!e#7XJ9~oK{GEMZNz~6$m9ve~!Nx61qF5@>n2Q}%IM_aH%aN%}K{9)#1W)Tm-yYmd zXI6<4b!p>|zu;D*LR94mX`66=!(IajWM-pJBY3iYyA_?ZM8Vn*oY{>CRYoF2Y1P+k zhB6a$YPI=%%(=|OPUgeI98Qxn6l@77u`XU#6(c$IPjp0Sgqrdsj@C8!rU6< zaI5-km%iW({e3-ZTYwv1oc5(_xbPnhHyl2__M80;{Rh8Y%5}fhUB6v^xc1vs@Y{=@ H-@p9){j5WJbdNTfz=lHFk0leSOI05g zoP>o4lZ1A#3auf+^v94jJ4l%n4XSp!sJIOJ8#0P%YVL9kTr)3Stkv$BtL7XSoGr&P ziX)H;2@9)mrfeI>3D!(C$r#zT@7Qgp>9|hocKe3i+H5-Qt<5UDy2hEWsLCzR>dFW` ztA`4s+_Uzj>L)P`v}%X5kcp0qBAXDVVy}6Y&xB{uB6pvvulMfDpj z4E;GG)Y6j%T=T?VY1D48&@i>lhPxBaCG|~iFo!NadufJf_?enTp)EACDH;SJ! z;oM&&T)lqfh;RBD`V)LR5WmT{yv(!RWG(ax|pn7w1V*KK$Ea|b&8MQ`WqV16ppb8{X@R8&#jjc+T}G8Kd7d_}9*F9$un8V$&(dwU^mx@A?XIOO zhKW_F9wvtewNqDn%Nt>R)yfs8EDQWv4P&VmIJ}0@vJJ4ia@Q^2+?x#e+P~uOXD2^< z&syiLn40ZHqtQY%KI+xHwKdEawJWcA(Mz|a=C4dm@mK9tp0|8zVK}(GGdqT{mlzA} zS17BL2;&XAlGy>1K=(*zG@d#!-;;&B;+vUm@)PL)hM8yg-d#7{xM%;t8>i;mAgrfX zFJGP#U_{hj?RhKr@7ulSrs+LX;}goUjkMRbfDKW5jpv!j z-&^z66&x#Ny;rc_cdmC?VWHT1u%GlSDrUj=5i_=2e?9$K}Jjdjpvh)%#**k6>Mhgqp;q&K08*OrqLEGXTJkm8pe_0oAXm$_! zN4j$s*1rfA7J*fVw?^Z!ZJfVU5dJwP%nSxSO9_|^v|oSgd8-d^ogMTBwjy3881N5_ zb{EsDrHq#g2A0XSU<{+<(M+#nA^npep~w}7w_-aS&&PT_M(%6MeNko(p_2%q%{Q|f-)Kpv2(Xj&=(%Kf0+r(qVC>duK=AQ~CMn!;;qm&Bk-^XE>qWOta#eQn* z{y4^mqG2>YvJ~`Uupz9_!q9$@9&%U$)f|0GchsHf_PXPf73QWtfeOV?gRN5Rrs!CA zE>eqA1))C{Lhx`yCUkQ&W2wy_2_Bp|E61x)?jH(1d|0FTmNL~*l$A#Lr}40h;~IH<-I&7|mhC+s4U@gaG{5N`XBm7I3sxJy}({f+sH&LhwpgqJj@E z5LEbcE`1=iLg~*J67Xa*B`P}qJVA#yIXb>WoGQ5a4Vi#;#)&JNUmV_^3=a12}lgJFWlr;=)^*l!97;&TouENxdiT0oz-DEzum zfEv!%s+xo0bjQBs{8hnwrsrKGdE#d}V)5V^LJ6v83ij4C_hn(DY#lTN@NCJxzO&Hj zw=r4R=KH4$0l1h;UtYXgI);aD4I>^rX&cFDA;)Fo}2BZ!E%nA&f$HmeIGO z9m@XQB0CVWsPyI~(&q&oQX6hQxzMRHYI=f)nr({1!|;|Z{Cd0{5zM0nX34^@nYRlj z%AY9nQcIB9f{F4cn3q|YbAs6|FfX?-VXgb^9hge<5lTXZz0zK+ySUt95dv8Yp}8JX zCNvm6VWExWnt5i{QAEtO93r|QCueb^BY23)vSZ!OaV1pPE8GLa6wP~mZ^KR4U)%!Y z8;66%1xo?5AaTVO(M0(Y(9PEifW@43`^+#!aY>17jCKI zQv@A8U!Wq=+#8J`llA23#f62z(6$OcS;)Yni(?t2$H(Jn_GqlN`)Jgkt1>oj6H@SQ z84kCLrG5Nv7^Y}`_(E@Odg_3=rM|xe2EzrXH)bT24Ym-UB#3bFj6BiNk)9~X@L*d; z#_@54(>vC)BSjUZHqh8Lh%U(MKt4~&Tt+%`TkgCX|QTr6dx}Xp`K=; z6)*GgAhxduk9CGedV}MK7yJG4EST<_hlS+Lp7*e_YEw=XlvLj0BWkK!?^e&d#3p!X zuwb3)4hbzdy1h&**3i{wirV7fK_QBOUR)+R9Ubem<1t}fqY*G&*IRU&EZ-iPl*K2I zwGcYunI%41*a)*`V+^FJKjnt%^J%YD|GWDrZhvr$gPVjH;-8+owU|8{sk_wyp@M*m zG3+RQzaYYu)31w0om@aIad@2I!hzG&DzCU|+He&6SV4sgn-wiRM{cdqr*0JVec16! zx+;BN|JdLT>+S_C-G->gI-y{x@m|3~71p!1<+&BzIyVR!BsA^7Vp*PD)Ak4&YJ56N zV@9UrYLn*f7F_6Tn&4XMc)ei4@lzGk;plaO0{TN0C7vhtc6vCaY)!JNo%TK)^iLd| z8Fhx3FfA@zEA*g!{-mDze`D4}hhUdbK{(o8u3{G)416mt#*dGfF0R+|3q8(l%%w0Va1saCTdPoL$sW2c-(9n#+YE z)K8mKwDg551Qh{DcUPzeuF8%hY`JYC=rTcuPd?-I1AlvLU)I3g;;m*U_L&8PKHqkfTV+gR@kCjAr{ECI>lX+5J4=o2%7a=lZeF+ zG=!Ew(`FYHlphuzf~k4v250P!7P>fTcAt(*($1ajgF)tKMB8qb6vm=b&>4k0|LvQQh&g{wAUgx@Q z$&Cei!n;UFKyFK3!q$Akj|+te1SkB+L@c4$DkLsO^X2@o@L;P$h;Tks@sf)basNwy zPGxTgvF8J_px68iPXVqZTv9^cteHkAmqjY18|4=GVo z4V;8@Fx;zBMV6>+7ILWPwi3Cxp4B@es;J`(b=4V_Lo!bzrertu`dYnWiT+C)) z>qr1ohaLU+Jfn&wSg4NHK;YE)XFU)s3vrDgB0g#n;v&Z3=RQlFDnt;INfE51{kY3m z!?0S2z$>+qNl&zhr7|mp1mw;U5~)<|hDBkOP(ZELW(pS43PFOvYLFb$)hU7jr_WDD zJ+?i#jY4nW<5kplAXzR{;KM`ADv))zVqM5Jkl(Y)Rb4Y7q&p^ReTh}n5w%cgq3&0h zwU&GmQ)dcp2N8$!jMA2FuuN#cRr3{$_rown^8;&iei7Fls${p6n{*X!GmCG(YT*kK z{7e(em?GkfCR=exe?m74T7~6D`A;t(o~9HjXpU0z=Yj}lFZZX~Iw&r&Q6Dq4*XS?S21OZ{PC6wL=(-h73 zpPoECq3%xIeRMEDB2!&U?8Pbn$$vy_OYcGD;h_0N$fg6V`Q`NL(xix1#Zos&oW}J_+it1}1+Dh=^g2gD?fTA%p+(hI$>nuL!-bVQIAJo!mc&)a@~rm9_~9U01joU(+enHE}PMv-ITe2r+au zTU}4$a^wiLwl>5!h2FQ*{8YiYgZ-pSG7uGJ2(*K)G<+`ibGkFcUDbO|bY>UPHr61* zH?4;;S>FBfdX^}DNvNT<;}qm%tu1u)SnUh~7~e=M=&rq2^D~0~IRk&ErTk9|{$~yR zLQ*n2@HYQj@G(_f#&%67p4k7Ae{=2vn_m#Zi1CFbB6^on@&tq)fe4BYFr1Aq>`n$4 zd7M~Yt-+R9eO^exz4&_Ugp`Gi=xRrx^oZ%Bc-~AEJLq$}g4Hwr*PEjuZmX%D!D)U< zXro0RRi>T(TempZ9vUF=WVyqj`3WJ9q8?+E=Zd}bjm#%S5%(dsB}G_b3xzO{+m5yux{{$E`TW<6(R#%V-qvVl)NDpG z&6xpi_n2>Dx$Cx@?Pz#M^C+J9ntJ5aLVpfI>Ep2n?$koB5<>rm14yY*w~tGXqmD}p ze4_Pg?7m91dfmCBW0w-xMC&zJpC**X!>Es^ukn<`xKbq{LA3rIQ?*5|l6%k~TCc@T zPShKzvC~|@Q-^T{W8W;X2bE~O4s(e~Cicmq11`~eJ(5 zwBCp#VqOA~L59NB?BEftH;E23!d+i?blOYk)?gE@H)BVly~!z6?AH(=T5rKzT`pEB zN}v<1yF^c94VT)pp+U6Xii7KOX~;o=X#FQA7PDIHp=IPjf@on9FLCb3V0LkYuB)bD z*L)zBfz~@poy)1YoPz|>dS|I~3o2V&(K#p(t#_3=ms4{&2MMC}Zpx`9RnKhC;jZF- zn~PbM&_RM|y@%tjTKImW#Mt0h4HbkjqYYHr|Hhmq63z11zHTAuc4-R@(3nTAt2vK%Lk-fqT$}v??x2;; zWO55KMC%^Udw4ZTyPMD1_PKx3nz+XGgnkeYGd9=tHVf&7ETRk$ITVX$VuB$ z8+Fv608TT>$c_bY^ZlHhTrDCX60Q4kA&~;Eg$PWdg>#z-NlwKT5>Sa2jz7t^JFd|v ze*el~*lc%4>Yndv>mxLX7LKjSX2+)Ia!{RpQ?zg(PiE$L$l?WU3+j>@HuHD`O{IRM zPV^MRK|0wB7{y$!L4jx?Kali>h4cb%b7roROCS<0WCoIXz98aq1x%uaTuO4R(<%!? zJWe}2S;-%;i58M4$wskL2L<@=AjW;1EI!UF-Kg~Vb}Y$+201c(;WvB{8=p5??`uBn7>iWZWwg_y~C+%jzvsb3$rcVi5p|X#KF%6In5f5XeO9N1URRCyV{1Rtj{Ybw7vkgp{LN zpb@Pf8@#DlG0=(DPjE?5=NRWrImTDe-t$_o{Ga3)Q5@0wDf=%%noCwz%*B9Dw0_3L zXi_Wgx5*r9-mrm9w0_PLXr?3+6;%=*kRT%b@ITElDh(p4aSsOfmX>2wR3h?4K4((K zG1L{8hyot=lsi>(jEY4>%QzggLX{>{G$N|=q^2b*zZ~q7;Z|ZK-oP zHJ5XcAfk1p&dKG;N#EJ24k8h4VfLa##2zs)iRgSbT%0tjnrBorBD#Q%#1c!$ zGb$z#UC2>YRB??4P>E38rXd8P&LB!<>m_#(iow-(7LY`5viRj_nOqVOUoC2MQwsVozQcKD+ zDn1eIU^g&nxg3K45$)u>#@tt>Jfor!(WNC4?mVNS5z%D~54})JWA!|v;uF#343A06 z6&?r>(G_K4xzwOz$U%UJ9>F0eJJaa$RIC{2M06dVcF=jo6ULhvUr7QIjj#G2 zBpOwDM6{b7SRE7OU6Iuijfzi1*K;+R)QUT*54xe0^bWQNc&;6Wv#y*%xe$hgKjxJ0y%r#+=pInf9f5j~dUK`T^>31~$0 zI3CrsM72aCcto^cbReeTs#geXB09jiRC)725{(cbqMJC>3u2X`1UeBN6g`oCEwyJu zgNP1s-z{8|dX*f62oXJA^hqgHWypa`M29)+!!fB-$sv%5Xqp=db865rkgri0Fx>&gIlx&Ow5R zo3CB9oTOF$fURQ@He$WC$JO z08}D+Du;QAjLRKxiKxk?XEIF~`(jF2fki|uE}h(vUR>5CE(d&IybqB%BPoHeSP zXatRjj?$4>VkwD6Fo~$kQB_oNjRsJO=ysl!Vi`GcTh&=E8U z5Yf}Pf4nmH|(V-O&sXO=jYo0J_P1D}X~y~MGcmdh~+5Ycb&pqI-J%6eMXK9Gs%H@SG` zgd7<;kcjBFNkB5&br&sEO=g#Y%xrM8CsfJR#+%7HCBDy9RG6Rt$7PedPDl z*`uA=JCd(2PJA+1e|Y$HB;fh$*W-EYxlZ|qhw(e2_J-njfc10R@1PZ);eKc3?*PA3 zu-@f+YvtEM)fd)1e2kf&z|=*(OOW1;m#!R+KgKRi^{WN&YeIdgxUqnb!A7z5UALIRa@m=coTBRd$wX?>0FMY>ob7^=M=0WI#u|1=JD)A zA|AJNdoO0S025Sl^SD{dUJEh91(>9g2gY;RE4M>patkm!B~Qr|HSCUvX)VC~l-yp= z<6rLCJ-0(*ehV-`B@r@f*&P!zT!0xac?_$IH%G~bWZgc2N(9ehdZbjw?hd#_@NB$a zE_=dFpMFGdigTlQtH+=(ZqPCf3&;_{bMO+9rAgb}h8__-mwhCE$a2RJL?U<|4<02V zc2~e8g6DJf)BEzH`eQ;BA_h7Uynvn7C}npGd?I)u^IlqOzSHh5&L>x;Ozj625xj^B zV&CcxFjz$J``lYhD%h(58WH>fCDir=FRR8|vGD#Sb<3b~#k3qM8WH>+Gnwrpc27# zoMB63lKyLs7Pv&Po5M)y7_NO5JpqdduICug3YB648WHT_x~wJ2u6-8W0FMZ65FLnD z2CG*HY$CXk3##(QeeJX876gc3FX!KaSfwa|P6YczPo!TPxdo^40++=Jz4B|HMc=?Df?GHjnY3JvL4XKu<+e1v zXlZznOVJ|`iQtLcmKH=@u7F7dxb~d9KMaQ!jPlY4EQ)@BMFhCooIJ5UsgSslT=y(W zh>O$#E;4Hg72ne9o<#|9Z8~@|S1x#wm$1759uYj{fn4`2x&;{`c^L5W+Ou!_9 zS#IWvDz4E0DiO4qx{YPzq-|MCKq7(;+a?w;UiU0k21Ft_k_$<0cFrZoiz;9e!CWpR zITcq(KqZ2soRs4l>65?ZMJ`3Rpg{y(Zgy;XE(ak(1h;c$HeRZ91Pua2a0i!LqnOJz zC=fx9y+I$YdCAh@5{N`F&)!fFak&B}5%jq$*DB0pX7h%5z=BN#18$_tm0V7NP6P{F zptY3kx@WOpflmZaV>d8qxg3K45ezx6F(Xm-fJM7EB2l>RS(E^c2*wN#y--V| z@w#VG3w$D2WOz(kuJAyB2#%GBmcb_i zT!SvWFD0ktats1QP<9bJHz_+pCN5$JWf!q?S}w=LMeN`iJmjgoS2DkwUgT2jVjvU2 zuW<3q2|2a`AQ8c@mU<#9W?6+nCW2q%6s0_Iy~w3lDbR`FnH+4{UR8!B5EJ0o|Q~rFP#bb-=_>N`Tc-H5sl!^ zN*1-iC;T6B`I^*NSX2U=@PEWJYo;Vq8)_7~P^+!ZoQ^$w7z^L0$AoDO6#|DJ~I&TqfX{)T!hU$VAZK&LfwqGw-m9O$h}eSk8&X ztQLEy*RY}-B#7XYQs;8pkKB%-s0IZhSW)U+PR->UB#2;TsdI8c%kQ&_&Ow0)R+T!J zQ*${72_jfcxrtPrF)La04iZFgD#w*Y&gC97h+qwu#R_*I7PMrQ7j_Z$fajeA#uYb0U8l( z5)vxLrJ2cM8-Ydyr*ZXy7kLT08{iSa=?^3`S#%3BL~zCf%1jnDp+f{`GT%{>RJ67l zh(xfN`Hm71d&Iybg0t9gahl1HnJm@@G$J^gj>Hn?%w$moOd>dkqpGOl8V#Tl!MQwK z#WHf@wyY;05y5$En^?e@nJiWYL?YOd3rTKCgU*(fW+saP1Ca0g5j>RLz@+7J z3<5;(FwSetmX&2Di~fK{1lvj^3Yp2G1ZYGs#qiJzwKN(tlSM7?iQwT3k4eiF9taS@ z_A;?tGSM;QAV35=IOL>fIWd=OP#}VxB{7rpxNFA@J`r46Qq7!}%P|NL!DS_mgwM{x1X3FT6F#XbrW5nNg7iL98#6Of7E zk({C?(uox-1v(Ktio zJ+<`413fENxbf8gUZ$XOjmEdlWG8~!JsG8T@BbvX`Ole<|1yplOneU{w+TMsznlx; zq*gpuT**kV3IAVs^39ZFf<%pDmmDMr|6jSmDwnI|9yAF572NkhZ!#%qpJNo2@L$OT zW{HerdQn`$e-#gyN~dye6D-32Hx5CqP$?#$5&o-rI@A)?a+}~0{%b@BV&<=Ug}^5K zf9LeAym&gm&dD{%^idPE-pQj znaS7}Lt;{~2>;z&dL|VTH%tFJ*y1nY^Lau zS4co5{Eu;Bw&fxnZb5_aKh6!0P0!^ZL-&C<7|t|AXh97Wau%X4IWu=$R)f zm=pd#G7FWXvUJu*jXI+zkRbe*qC%si@O*%;dvQOazsPOvZM_2P(D`&cb~htU$}i5Ig-%=no7SEPj=+i_WGk>V6r`?&vr1NFzE z)IV8rpuiw}_`f>!`Gh%A;;dNvgrCkng$`@%9)HN<5TrkP;Qbv`!bb$cV^ME0e#Mzr zxHc)yqqR?-;+>i-#N+XBWOVX5)P|GK#l^^&GBX(T%oLar{_{Lj_{wK zar#HPb4J%-NBA!wr`^TWZ7v6Pg#SW}hS;}m+f0BF;lIf9*2aX|!amDuSrS-Zmqt`xN zvB=-cI6jI$FIS|BV1;r;@}l;cisk;UC>K7Il&hX#ve#E+I%=P-SnltLa^XWh#O@+R zLZtS&ibejmC=$h=nud6E9PQX%C~ZlRDyeeFc%ow#VRjdB5WEB5bS$%9bZ8InA2p>-B>R)bb zmoL#C)&FwE>OUjn`0!GfVs8B}XN=lcDwgug8OKM7EXA^HeCyRJX5XKG%}$%R|6YF`!BU-P_ryE8v1*Trv%+SeQ2hFyK^ zAG_@XQNMenGa4J$$s=T8m6-D!{wNE=Kk9kQdfl0vJ1^am{965z@VhnavlDl=jTRRc z2E*~TW0&D|u0vU8O`RtZ9`)^SbM?Ez_IA_TTnl0KVM_RSnBV5Aen z%3Cjr>dwziOhk0bgJPj!#S@utjFPY{UkZ;^#kmnWk+jGdF9HRpQKXk_#m z_C)x1Ni~O^Bg4+8KM8XU&DdiU|MF^EPRQvn*H> z;Y+bC05eIPBsZ_67X>D3$+u4{3K9MjUfUZdI!rA914509tV>Tm<;}k7FVG%c`e`+X zyhsLx=+v3K>5*{%X+nOu(lugqrNv1x#7VKzh|y$mG!Ahzwu~4}5&6>)`Opd@MpH%l zG(;A((umPy5Qq@@&nhEEb74<}NPDVk8b*w!z>Ely=~UHpj2KOYIT7OUWF9e^0V^VW zNtF?!nXo28Br{99yfzlu&Jg|6axbs$^Fykm&ySY5IwfhLI17e23s&lsnk-TgA@T{8 zx``%>1Vo4gL}@^@vB=Sc7)K@79BAr~L?Fhe;^>`RZcr(=!jYJyP@Fl!-$6}~cj!e6 zqwWk6{CMf_SiO(jxLAWggum-~>#&WE-(Rk>!R8`iNrbb+ktUDK}t2ag-Y>Du> z$SoMsuDV9BA;RY&3b+P!q%-XFXDzjX9T7esxdmrsU_^vS<($n$pXpc#9P73_g^M8C zOOS{Vshth#@==xcf-MmuyR%;LDg;p^fKr6j!iv#5K`TV>B+kTDMz1*E zhp2Th8qUg=;Tq`og!X*)a^PXC)=Yq?-oG z|6GTQx<S7SM%k2KK1PrqR> zob9v^;#_*9H#n|(fVoUDAQ~7DoA>qGopEP4-|a`^4w_^R2S!Vah?%2-X<@_u?r2;k zG-3*AV0u`koW~n>gmN9$LJKB%LcZM>u-)` zs`Njx!)##Jcvg;VV>>ybGzp;cY=*=0=e}Xd$ z3Jb!&r6dbVchoNl|JF)bP))s!M69__c4R?s6}C^To&|*|;Xlce1;y_O|CdhjmLa7) zU$%rQKMDUSb#G(4Gu!EPhM3=)Ph0Gw`xheLXUm;ec$y%fmHYdb7rnW9wlFFFY zeF|%hZt~RS-lhogR$mTN>tC}h-=-@(pE1LJwNw+#h!FYYrKFl*PK3zYRmu2>^j?Tu z+)^?=B6SyHw^kwJBldJ5wrcJisg9%A*oD}yl_of}vDnb5PMrKoJ}F$T2lXMXUwout^dG`2#+kS|G=CG=c@G|m=WR8rS%_}6JfVf z|A7?|-oB*%18X9@!_|LaK&ZyHWDMCS{1yr5K#{8h&1S|S8n`3@r*)&u)SuZPCQRHr zwivI_&GcfQaoRtWNraEbhEC79GPP!8gF%Fcu_M;(WcD-iU`vG4xW{6G*HmB4O7A!| zYJf+C*gIsa#Zk3hjgAhEJ1Z}?93eIoXK6Q*%#M>UHX$MQ8S6A3v0pSgE_Ng#whikw zYayDmEU#jR5n|hLdY%^Fi)$=WY%@Y^C9>dS^%E;Yh-v)vICrb=_Kes4Sir~?(|*`ONQc;|b&qv$NoBOy zGZzU{BEQd!WqxolH6sR-M)<*!|@s0NTuL+82ts22r);k)Y;GSd)a(p z@6Y;Td{&>FZeoF$1`j@f@d*wQVxlXgP}u`~G3Wa2nztIW$8bEmI5zju0~Cg9aI+*o zsl~-A?RNt2l*o2JXZTnl{5WHJlHwsuh;Tnz#gLxV_OKyB)WMh&6eHKa&5{!o`w9O@ z<(%MN`hdvov*!f&3Dd_SZOmz}^zhjb6J6s;XL@JuX2-r^7|nO~$Is80Pvl~jYajrt z!0wE2dBk{x7g1_p);bTR#3$oj>Ijfzz^0SCZOj^CwrgPaI!9}84Rp!3D!^skLI9{QgD&oA*z(L@GOhxTE_N7}6r;Ip5 zG;k=;RY78I_6{do93vVyAe>7lz(&fqQZ&T5qJfjbI!YjoW|@2JW^4foS0Tsmbb+w=-HG5DjD+HYX+Dd~`S%;{iM;T_h(O z$Tn2UD2uE_1L=k})7Z}>9n2gck(Ov6&#)F*=sP;21>AzwF_T0>LR~(xexd#wi~@3) z-$X7_U8|g1?9P@ykOK>%_N^skJg+4S$HHCCj3+Dz|2kX76Tc+<-SsN>eR6l;-$)`n z!Wz9XuJg7_r?zkF51P?n0nyFfFsg}SLHDs@uU9MPiK%Y?_Rj2h+YTd5EbcxwJ{xqL zx9yzTK2x|qRTn2VNj`Q!n=>Aty+Wbejm3&hlaCFNttf1u`_-Z_E$o3WPSLOmB}u? z2JWGaYn`GI%Wgp;U#={ZgjyiatI5S;D zNL4qCAHB;x68F+ANd;=(VnwhNf7`vdlIKrlJpbXQ#Z_Cwg7CMOEUwxRza;z}ewD>l zQ!ghGi|ZBG$o9Ma&Y;&$AIlhF$-|;Ixn^lL7=-_b@-<7_?w}<~+UZ=gG!3SNe`#^e z(suYA;a|4g@kj=ICHyOwdmGir8T8c~A&|{$&J>;=WhtSka0roeqc(3zQ{*}Iv^=gy z;*AQ0^rMy#WrtTHe*}s6-H|FO5Wj;KDKLz!$@x?B` zE4}!~LX-iaI#}k`m1-@? zEzpVZd}K-C7B0>YjC~3=M0i0`4RuMUsow{&5cNAfIq>+|T742=ODR4PUZ`H(nT=uj zQlhkt%sSu_;nuuPNduX6z$LUH*C_T^&$}@M85+gbBLzrTES!EdweM zUXo0W$_w$GOotyJ5#fU%kWK8Wn<=uR*Mmfa560v!1o~C@;1J4x(B?29 z!qd%{-?Tk!i0}-^m%Vc&duBqJ5FtV|d8($YFZMwG<;7FAwiAb5ABWy`dNa zI#?Vs$6h#iYC0%{I@3=E^cCMsep|bXRycLOwHQ!s_ibVK9alif^2O5QKe*wYrm8*Y z<1vEi^aWHC6}a{cs zgr_93>d$b6y5~9#L!mpQwb{P!O$kF;d+I+xJ$ZW;naSlwV}H;kuS~cxAJMpw{5>bI z!)vQ!T71Ed_afyl1Yi4-OV9-5dO`X#nn>5c?ZN7V6|0fc$7EM06pF#FU%I-6)9@p?8Hs%LbNMA+4i7StWxrb;Oi(YR4PF_jiM-N|McJ~726 zQienWG2C!NZxD_5s5kgTW1F|IB^vt>`betKz+4z?iN-+;=tIecs*|_G zubtbAjH9i^!5|u#+}7WGa-mb9?O;kY9uHbvnA=yF5^6uNOuZzwwC{h1W*A-H#c;j} zxzk%Z;_i2(*obt|%^eGW0|cpFtUFv%M4Od_!%Hg1h;u}Uc7-odc@bY$A2-t??W?yGp1 zLje}izy+F3N?||#i-v}~qIB7?CK?E+xskq3Gt}-IbzBsPw>5}f{K&U+2K}C(e_yRc zxFxlXhba2#17_;MEo1%aU=Z~m;DD#1(cBx2;u}3U;hFAWU|kiHsQ(b}&5ulBnOm-dmGIP2J^V6mM)J0~Z3OFgIkJ(gz?} zma-)p4@X8f&nxRddjF^F)zDOE?8GKC<6^PLU8p4sNk-ld7Rg9<3Wv)I)jPw+j<~$| z4^`-C*F~d_3XQSIj0$t2fg(4lKA@;7LiR#oO*C+_TB}&sEq3h_Ck%TFyX->`4RJiVf+rm(ErenT-Y#5#%|` z6G;m-m)q8eZ?OKDMZdWQThN(NGSqNBEQ!SKzv-<_81?({H;#J>>XJh`xOVzeYjz3k(2ch~C^1&1-m>Ipm25eEceK#O za@Ku1Uifw0;&_a=pO}{R`p;M(9R4{RmfV}24ue62_+j%6xPdG=GafpM1?N^|(+1|n zR8fc!)7tudvm-RqbaH9V=(92RI;IVy_#uv$%2_Ps@gwr+Qszp+mIx83HQ+e|BLW&WaN{*N_K3iU2$v)Go$P?n zZElWcbZ@syfJUeUgmGKrKa6G=UE7xH1=_kB`E~F&xw?-zjqs5oUEA&)>+}W-^Vq2y zNj0^FNKwO>2YNyux!E4xQWZ70UQ=mywaI z2!xMy{nYs`Zb^z?*k)`IvHYvIB&|?41>zAiLv54^;bS3RmA=y0?2=gReXQOq)p(hY z7A7ycv1cnA!pEwOi#6(1Cy1>_~OhLNln|M)*juFGJ?E zv`?#F68@@H-h=UG+Ntz*pT#b&VyHauXiD{1Tpk(B;L|mDbI#;V8}zaMerjQme!%m# zD76`g^g4K3{49vz<92P_`w~QAb z2P360dfFnMjX|b#HX62PkwY=E!652bg4fUVaF-(Pr0L@mLC1EQX#OgaFn6rR)HX91 zsx-5~M`c3zr($Zu8lY|%Hdaa*5&jySfH3u3x@{iMW=Bt3j7RmqHaZpS#q zqz(t8(YE+yLsJ$u7=(W&T1Rb8u$RObIa0b7!G`cR!_m}U+&*gz2h0ioEbMH`?il2{ zp$rKBY;8O${iJ|0ApCRCm`b@hnvZ%tqcbog{BtqD=A+SU@%5S79heaQc{m8hTN|S| zEC_!Kf;yNT4`y)_fob@{hVai<_UQ}lO!lxL{0r2^r#mx)U7yJuCWL<>w*HoHIjG+g z{?-e;)6&tWKGL9;=N(g5n2M?YGl|$QybM=IOQ`m_8YH6ra_k=`1k~2RI64)9sQ(Kx z7^P%;`JfT?e?{M(khpZpI0GqjqW+3v-4)edHb_MMm6K)fw8kCgMEzBhWhYd7*&q@1 zf18YZvI#K99R#BO>dCm1Y%d=)qW+p<-EDD)IZ^-jV%^jIy?pf5)!$)G z)L)0POQ`mGgGAI{kGM|=*!w#OMEwnjdnwsoK4?V!jm5g#;tq47{-$Ex-EjwrsK0r# z?(8;(2~81*`dcRJPO`o3pb_=ECdhH_d z(;ZpZ6Dm2dQoR#QCA3UC)2+0|&i^88Q{tX8GVXz4Lioswt{SCpdNJmILYhOr0fKrp zxZ1lK2{0o3<#1?mgcnwr&0#{Q?B8;g|1l+hYTu(N^2FcACaZHIe*Le?{%piyqju$0 z_rCv$smG%D2COvW2bfY* zhPrLp!b0O|7Q)v!Y_Wx^wndj&sm|w^vQ*{OzZbf@SR&f*@pH3E!B#8??f0(n*2Onp z>`pG3m>ch_!XtFBO?#4gOI=`9SKKIX%+am;GnoF ztAN^bFuvFWU6Dy{;s)a9T|Yll@EC{_buTbXW* zrf_u?|DIj|Jk)&KTG#^URxAa|#LShll>A!=L@Afj9;IAXu@op1GmpfW&=EV4e>H?C<}wmc3?6T+)G&}H zRDWEp?+HOKY|38v<_9HqGmpmKLHhG9{5aPsKPIRVO58KK^*?auU2jT$89kdu=!eg- zZ~X=9IfC_EJVAL_-y)N4`VW7+l@{#(e^??dJ)cK+V|A-Q06;+t$qKq$u&^;@d6?FLK%*t%~`XNo~bS>tUtM zPgp`;EquhMO5d#`jMZL{P~SW^PFRBTeG>5Z59A=vk3PXr8zSOM6-$A##t&sF`3Xyu zqBh%v`hacg70KnrI3z+g~m^D?+#CT$;!HG@bE*)udjZh zHuJ8267B>PFP=-2JiG25r8ZYT2|v_RVi$E&4+F{-Tez#z48+&{@(1vRIegUknVJLf zx$pkm#CyAiJ!~|7j&Yd#CZ4dv7}dBho8*%)2s@SIAikmAlb1gr7wl0cQA69xwA-X@ zEuGtyeeD!H-ZpvE<-L<>ZcLwaYo~(o(4?3Ex&Hw1403JvUA7nOp#L zIq9}Dwnqz4wJN!;##j?`GqqarWG}dPw^SXHFd+5g7(lE5wXe+P1 zw%9QX_9A@kb0^CYX-L-Y~4{v`efV(3oeF4fxFYfeURWj1TPnuEcf~jx}=4#h9LdkhRbe~ ze0A6SzW$McMM7<`DS@NL1(OoVvzxe~I>Lu9%@N!#WN|wmnZ3^+4j*fNO@pGKkUIQ1j3~IV% z(w$7k67(HH1ns!JAQFH5@L+#QfkHpho;@7t&k0eBJFwPFxRwqR49Mytu8SGvN!^TbwP5VBCv`K@qXg+1Q&KlG$5OAo zy2_f=%{Y$`9QbHX>Sh#`!DD>kp*csJQQ(cHTpP!${7PNMP}wLJ@)$>sHe(@3nst3? zjyAJ}sQvYru7_QU_J)RcL8{KHZd+9`>H&K- z5f?hYPTRImheo=8Zet?2WKu>rt<*{;l}zglp|u6CYH(;-ygE%NVH`iqp=8>yX0B}# zf*9kQCIl_6oGF-C3eHKHd=V4lT~NqcbR!hlqNv!Jse%e;1@;EPMlFn)cwOEM2s}Q` z1UNpWXH8@+#g`&P=3e=>T9J^;#Tg}^2os6FHzzjg&*&|IIkBGQTSWpT`mrtPB1-wG zDCK8xOedrB86?3F>6GXv6-$9K5&hhfK@!FMgalOorxlBVG@+VhGJ&m+kSl0~zgJEk zA%zcb$?T%LOh-szf0wXVFU`vxA%)#rh27g6x#hdwlo&^E6QsAx-10`|#kpce_%&yl z=slPf;fJ_7BvJ+|Gfi(*g>OR(s+uzh%xcd3u@3$!vhX*?fjxhG>si;P=4!}bc*VdG zJU?uNUn=!OtO-Sjo=op*htxbuoN4Q6qLf`E;BU2IFbo^PP!k)mxne15zd&HgHC`za z#i;d+IIChY;_8xz%|J=wRmbWqYUA&-@iOpHmhBVy&-8+*a7&%q2%IO^3*Hd#naF*U zThL&tf#chTBqh9Ubo`3#+uIA<@K~exW`f{hCD%BoR^81sXBcyF1TIO_>PTSq*4Tp2 zXQ*3gCbF&~$95rX*?S>8nRV5wSP(RjvUHdSuh#a0d~l07nUACQa6{SrM{?-TQNJ8llQ+QDekuS;qNpQx7~{xrUJQb&m{R-PfW>5 fgyg?djTopuYAQjW{u%#+_}A?J%YRCQ%m4iUC1iZ| literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources new file mode 100644 index 0000000000000000000000000000000000000000..9d1014f634e5cd7c8cd3b8d0dbd2f2fef0e9febb GIT binary patch literal 4976 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 F{{e%0SEm2~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.adt.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.adt.prefs new file mode 100644 index 000000000..1c5c5d530 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.adt.prefs @@ -0,0 +1,3 @@ +com.android.ide.eclipse.adt.fixLegacyEditors=1 +com.android.ide.eclipse.adt.sdk=/home/jeremy/android-sdk-linux +eclipse.preferences.version=1 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.ddms.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.ddms.prefs new file mode 100644 index 000000000..edc8428c1 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/com.android.ide.eclipse.ddms.prefs @@ -0,0 +1,8 @@ +com.android.ide.eclipse.ddms.timeOut=50000 +eclipse.preferences.version=1 +logcat.view.colsize.Application=163 +logcat.view.colsize.Level=26 +logcat.view.colsize.PID=58 +logcat.view.colsize.Tag=122 +logcat.view.colsize.Text=648 +logcat.view.colsize.Time=165 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/net.rim.ajde.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/net.rim.ajde.prefs new file mode 100644 index 000000000..188e3d1a9 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/net.rim.ajde.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +showStartupPage=false diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..dffc6b513 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +version=1 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs new file mode 100644 index 000000000..84ccf948a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +prefWatchExpressions=\n\n diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs new file mode 100644 index 000000000..44ea4ee1e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +org.eclipse.debug.ui.PREF_LAUNCH_PERSPECTIVES=\n\n +pref_state_memento.org.eclipse.debug.ui.DebugVieworg.eclipse.debug.ui.DebugView=\n +pref_state_memento.org.eclipse.debug.ui.VariableView=\n\n\n\n\n +preferredDetailPanes=DefaultDetailPane\:DefaultDetailPane| +preferredTargets=default\:default| diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..18669b619 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.debug.ui.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.debug.ui.prefs new file mode 100644 index 000000000..536506bfb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.debug.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.debug.ui.VariableView.org.eclipse.jdt.debug.ui.show_null_entries=true diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 000000000..2d0b102fa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_VM_XML=\n\n\n\n\n\n diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..c0e81e060 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,19 @@ +content_assist_lru_history= +content_assist_number_of_computers=13 +content_assist_proposals_background=255,255,255 +content_assist_proposals_foreground=26,26,26 +eclipse.preferences.version=1 +fontPropagated=true +org.eclipse.jdt.ui.editor.tab.width= +org.eclipse.jdt.ui.formatterprofiles.version=12 +org.eclipse.jdt.ui.javadoclocations.migrated=true +org.eclipse.jdt.ui.text.code_templates_migrated=true +org.eclipse.jdt.ui.text.custom_code_templates= +org.eclipse.jdt.ui.text.custom_templates= +org.eclipse.jdt.ui.text.templates_migrated=true +org.eclipse.jface.textfont=1|Monospace|10.0|0|GTK|1|; +proposalOrderMigrated=true +spelling_locale_initialized=true +tabWidthPropagated=true +useAnnotationsPrefPage=true +useQuickDiffPrefPage=true diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.search.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.search.prefs new file mode 100644 index 000000000..cec65c499 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.search.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.search.defaultPerspective=org.eclipse.search.defaultPerspective.none diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.browser.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.browser.prefs new file mode 100644 index 000000000..180dc131a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.browser.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +internalWebBrowserHistory=https\://developer.blackberry.com/android/documentation/gettingstarted.html|*|http\://developer.blackberry.com/android/documentation/gettingstarted|*| diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs new file mode 100644 index 000000000..61f3bb8b4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +overviewRuler_migration=migrated_3.1 diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs new file mode 100644 index 000000000..56d37c21a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs @@ -0,0 +1,5 @@ +PROBLEMS_FILTERS_MIGRATE=true +eclipse.preferences.version=1 +platformState=1335828588512 +quickStart=false +tipsAndTricks=true diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs new file mode 100644 index 000000000..08076f236 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +showIntro=false diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.core.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.core.prefs new file mode 100644 index 000000000..3b568224e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +task-tag-projects-already-scanned=ActionBarSherlockSlidingMenu,example,library diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.ui.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.ui.prefs new file mode 100644 index 000000000..4fd0cd34d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.sse.ui.prefs @@ -0,0 +1,4 @@ +content_assist_number_of_computers=2 +eclipse.preferences.version=1 +useAnnotationsPrefPage=true +useQuickDiffPrefPage=true diff --git a/.metadata/.plugins/org.eclipse.debug.core/.launches/example.launch b/.metadata/.plugins/org.eclipse.debug.core/.launches/example.launch new file mode 100644 index 000000000..8397b9531 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.debug.core/.launches/example.launch @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.debug.ui/dialog_settings.xml b/.metadata/.plugins/org.eclipse.debug.ui/dialog_settings.xml new file mode 100644 index 000000000..ea94bab01 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.debug.ui/dialog_settings.xml @@ -0,0 +1,8 @@ + +

+
+ + + +
+
diff --git a/.metadata/.plugins/org.eclipse.debug.ui/launchConfigurationHistory.xml b/.metadata/.plugins/org.eclipse.debug.ui/launchConfigurationHistory.xml new file mode 100644 index 000000000..d9f3062a0 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.debug.ui/launchConfigurationHistory.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.jdt.core/1440040889.index b/.metadata/.plugins/org.eclipse.jdt.core/1440040889.index new file mode 100644 index 0000000000000000000000000000000000000000..853e81b7900f148bd79c32ac12bb455d807651cc GIT binary patch literal 193980 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ȓ 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%0A)0jqHG8KbtWU}I!|j% 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.jdt.core/1577419489.index b/.metadata/.plugins/org.eclipse.jdt.core/1577419489.index new file mode 100644 index 0000000000000000000000000000000000000000..1157a4ece0ed29a12e67baf9a1322ebb0159717e GIT binary patch literal 27289 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.jdt.core/1717276877.index b/.metadata/.plugins/org.eclipse.jdt.core/1717276877.index new file mode 100644 index 0000000000000000000000000000000000000000..0aabdaf8f712eb1b158f26059bc3492dbb22eb1a GIT binary patch literal 139143 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 literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.jdt.core/1809425343.index b/.metadata/.plugins/org.eclipse.jdt.core/1809425343.index new file mode 100644 index 0000000000000000000000000000000000000000..107bc47f40337af038c4b5a4ab300305f65df095 GIT binary patch literal 1487351 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

yPJ- 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 z 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

+ * 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()); + } 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/.metadata/.plugins/org.eclipse.core.resources/.history/dd/73728eff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/dd/73728eff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..e84adf2d41604323cdad8b15e7034b6137e02425 GIT binary patch literal 720 zcmV;>0x$iEP)!1&^00004b3#c}2nYxW zd09!jyup9SJyH%;E_KZI5Ed^B*iNJmRSj zBG=jNc2B+cMg+dzb=~X>SwfDye{PH^oqQ4$1^~*55|NVv2=ckIR8XoEqC|oOgc2g; zEPA&fNb-^8#Mr1#v(VQn5UdVR@QAWs>EP1 zTHM9Zaim5tPqqk+y4R~ii**RWgPIHWkr2Q-rv~$oD_;OFg!*vQOJ?oR%RhjSvm}}N zU}~@)A@q_TOphE%y@J$^Y;2GXG*T-_?U?-%UNYKi5n>WcgjmBq)+~pV5UB*Fc4!_E zr<_OV^tE=(@|l_%K9#lBPBbeU!!Q72CYl{ozqWE(s>}kg*Xy-fB`%jskbX;(+jyxw zA`k(lb8|^3?6_RfL_?Is~gyeh`O%xX?U(f parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/de/30efe0e725c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/de/30efe0e725c3001119baa706e9d70c26 new file mode 100644 index 000000000..8e7c3af36 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/de/30efe0e725c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + ((ActionBarSherlockCompat)this.getSherlock()).setContent(); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/df/204547f6f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/df/204547f6f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..1784bce9d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/df/204547f6f9c500111689feaa37e8ab14 @@ -0,0 +1,40 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/df/d0fccccff6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/df/d0fccccff6c500111689feaa37e8ab14 new file mode 100644 index 000000000..114632cff --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/df/d0fccccff6c500111689feaa37e8ab14 @@ -0,0 +1,199 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.AdapterView.OnItemClickListener; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; +import com.slidingmenu.lib.app.SlidingActivity.MenuListItem; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuList; +import com.slidingmenu.lib.app.SlidingActivity.SlidingMenuListAdapter; + +public class SlidingFragmentActivity extends SherlockFragmentActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = LayoutInflater.from(this).inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/df/e00126e023c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/df/e00126e023c500111b2a8b7f47e59881 new file mode 100644 index 000000000..b89c1102b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/df/e00126e023c500111b2a8b7f47e59881 @@ -0,0 +1,37 @@ +package com.slidingmenu.example; + +import android.os.Bundle; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.SlidingMenuActivity; + +public class ExampleActivity extends SlidingMenuActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + setBehindOffset((int)getResources().getDimension(R.dimen.actionbar_home_width)); + setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e/024392ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e/024392ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..2cb34d7f60401a563454c03e266cc5181d9de996 GIT binary patch literal 609 zcmV-n0-pVeP)%5ec8;(Nh#y0Zthco9&fD+Scz(J_kqCSd>@N)Jrb#iJx@ z@geV)|0U|;Q8J4AW)%0$DDIn4+&81RZ$@$73{E^#CTa6Odr;zqGLyGk)zfLB)26Y5 z5#LU9dOW?JALQjc$4r{WH?GVFg))<)qMW_Ts@W~*Hgkd(m(u%LwVNxGwVfAK{BG$~ zHD4Zg33jP$CptYU%GrKa?RJ%hK*cvHEqE`!X=%Z0aT}!tZ^dnu7Q7Uk{&1!u)wl@^>7cUfAnUfgwQ!D?|Ir3GuneU%oh6!%$L*todw(!xf?LzEVJ7Y|ih z=v92GOd6`R(5v{nqI~u|T|T)5eQi`_Q>fI*QllCl)AthpQf>YCTIE0c%xyxW%x|6C zG>z*e{-?!>T@(EFL|;a6&!||%qb(l4cp2298zt1@mjOk(atXEgIq-{NzY%9xIi5qk vb6%{!-vcjz*7vDBaRYn@J|M2KzWDwRiVUw(_ikNA00000NkvXXu0mjfOP&sp literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/204a863e25c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/204a863e25c3001119baa706e9d70c26 new file mode 100644 index 000000000..a618f0e46 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/204a863e25c3001119baa706e9d70c26 @@ -0,0 +1,214 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/41c197ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/41c197ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ad1b4f0a8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/41c197ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/e0/509cd0de29c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/509cd0de29c500111b2a8b7f47e59881 new file mode 100644 index 000000000..2d4fb404a --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/509cd0de29c500111b2a8b7f47e59881 @@ -0,0 +1,134 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @param i The margin on the right of the screen that + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/50b38bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/50b38bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..0279e17a123f8cbb3c7e3a9ce5c5af8e693b6977 GIT binary patch literal 76 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1|-8Yw(bW~!k#XUAsp9}6B-)+^LX%RmN2q0 Ycy4A9FVZ~13zTN?boFyt=akR{01+Y(GXMYp literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/524289ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/524289ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2bcfd0b63 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/524289ff24c3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/80b3233a4ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/80b3233a4ac3001119baa706e9d70c26 new file mode 100644 index 000000000..f8844ad25 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/80b3233a4ac3001119baa706e9d70c26 @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e0/820a91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e0/820a91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..930ca8d95e8bee5a1240fba645d9dab919abd734 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=^`0({Ar-gYUf;;epuoZ6aJO@& z%&D0-IKvGL&8p&qV;O7KuliPO1yl(K>(rHwor_8Hg9|Y9Gj8!^hz0Vk4~QZ}ABcvv nF)(akj$uTI?LshtEWgbR4Rf6*RPme*0Ev6L`njxgN@xNAEX^ml literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e1/00d96a71f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/e1/00d96a71f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..42e526811 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e1/00d96a71f6c500111689feaa37e8ab14 @@ -0,0 +1,196 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e1/63da8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e1/63da8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..4d3d208578c61662986fdc16bd15c69759b48d6a GIT binary patch literal 922 zcmV;L17-Y)P)!ytdud6iMT7O&4bD*mP3eKws)UN7D2k#e z%DbYt@4NEYnkjlINEK7=*RV3zwml#Px9r!q%}Y$QM*NqHEZ-wscn^ zf4p9=Kg#ZZAKY%YZvc!aCbL}F6eGxtBSzy=smEUmc6C{?q1YCQrid~5o$!73+BeU$Ee{DI^Yo4#-o87 zao*xiE9Z<+s}ttlWw19HGlEA1nW09+*~|#}a;CkeJh%bU1g9CP5h0^O2}4Hs%y=Lc z5q!OY8j*^uk~rBBK?ljmh#jL84Ev;rDo>_H#K|6e%Mo=CgLzw$rI$Y4Z-kUy6U47Z zMI2w^tmuV~pH%tJq!^(yWY-hbFl2;G2g)+VPqud2Sicc+jL>MvBTKK;HbN#jlrS<8 zl+;FqdPULzJ~Kh_!?j8>!xs^*nQAm$#290~ue;BBnY1w&wMw4#m(pwEDZd_oY1{Ux z>$>N)H(eWD*FCpw`-IsDKF28-6~1bz!JGs-W6Z&R1n>#KR{&q8us99Q}8ID#(NJr3oa@N-D4Rc$qhA--bT2} z_Wpf@Z`4749}#V+fwWJz^oyZKO1~J&exY-1*Kg?D$hu!fixvAiNfpmG;mo&f5BSEA wlE;@gYed_N;JFm#Y)Zw{1W}kQU9GkF3xsHEK4Myn7XSbN07*qoM6N<$g18=|djJ3c literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e1/70e088d829c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e1/70e088d829c3001119baa706e9d70c26 new file mode 100644 index 000000000..99e0ecbea --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e1/70e088d829c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e2/406e90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/406e90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6d2039e2846248887058bb3243b39ae4d27be083 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^tUzqR!3HEvyN#v+DRWO3#}JFt$v^)8w`Ugk!+z0# zN3CbO-PcxbhE_M$_WcSS4P2`l4R(3$;_P!f&LP~Qw*UWzMH~!_whN6}dbKYDjbQL} L^>bP0l+XkKVJ9JJ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e2/41fd8dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/41fd8dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..b28b3b54f4c81d482f797f31936cbd4013c093b5 GIT binary patch literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE&~Ijfv1aOh{y4_S9ba-JBqkHTrZXEaifjpNYW7o zp-Ubd&IgJo2<&v8$G35^;Tskk#t2~^NlC?&yDV(Ca&uB1b9CBkO)cqrw|D8TKToRF zI(8j)Hm_*m)V}Gu(AmZ?>+lr!|Ew$fc6F-Mb^2PC^>5kCb?-yw@xD*CTf6%^rv51n zu|M&RMY8TuK!x`HjjgjxbG!Ig&nSGQ(EnVUqiU&qoaH15q1mNr`vuRlFlL+adKX`+ zs(G(GZ+*gGNpURMpV)N-wqLW)~-JKU!1N^uTZarp(au zRVr*pp2gnEY&GXI)J=?c?L+7E14!w(i?Kf2&j6te3n$Zi&Cq1Pnyg64!{5l*E!$ ztK_0oAjM#0U}&goV4-VZ9%5)_Wng4wYz$;u85o58|F#)LLvDUbW?ChR22(3jb0C6f zurM()AKy<=RI#W9%i?1Z!-*&tsfdKx^K~y zNvG)l;_a(%bh|~WUDC#VGO;m>#PA#fcXK9)`13@T{o9?nA4o;5o5Y-FnrEZqmiSfc_S zA{L0fBR|q&9nN(%dQPr62<8wn(&1H5U9$-)I7C2Z`JBz?d5{-aLE2Xo1p`HP=mx~aK1dX;9v%}N(nzmT@Pd`BA1%s63&zD(zzHm$q_hN@=KrCdw?apx zg|6dWD;#yE0peOH!sF1UjqC3vt^%zRB8%X#gYnU_ip?P=I2z&rRN68yE!*`IdyY3v zt?oy}@@-T%bVwCg*LAc5TH}IP5UY|Q3qqAI=cQ_;R#jwP5d>APEV%}@#~$*@lIvV^ zrH$NV6uf|XHc;rEAg2~$56n~6+%>TXikjaql+}%T3$C*!mIb%Gk;~CwxTLZFG&CCI^hxCEM!6Gz@BO~KEN$(cX6~la>6@7kg^L&H97g9q lUjEs6bLS)cvYUEvdV@KUvpb*8nopC*RIfISvx6tk{sPCWCuRTu literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e2/60a7b2caf9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/60a7b2caf9c500111689feaa37e8ab14 new file mode 100644 index 000000000..5cecdf280 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/60a7b2caf9c500111689feaa37e8ab14 @@ -0,0 +1,42 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + this.getSupport + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e2/a13a96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/a13a96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..2c428e907 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/a13a96ff24c3001119baa706e9d70c26 @@ -0,0 +1,65 @@ +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) { + super(context); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineFrameLayout(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 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/.metadata/.plugins/org.eclipse.core.resources/.history/e2/b04834e62ac500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/b04834e62ac500111b2a8b7f47e59881 new file mode 100644 index 000000000..882424023 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e2/b04834e62ac500111b2a8b7f47e59881 @@ -0,0 +1,159 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +public class SlidingMenu extends RelativeLayout { + + private CustomViewAbove mViewAbove; + private CustomViewBehind mViewBehind; + + public SlidingMenu(Context context) { + this(context, null); + } + + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setAboveView(inflater.inflate(viewAbove, this), null); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + setBehindView(inflater.inflate(viewBehind, null)); + } + // set the offset and scroll scale if defined in xml + int offsetBehind = ta.getInt(R.styleable.SlidingMenu_behindOffset, 0); + setBehindOffset(offsetBehind); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.0f); + setBehindScrollScale(scrollOffsetBehind); + } + + public void registerViews(CustomViewAbove va, CustomViewBehind vb) { + mViewAbove = va; + mViewBehind = vb; + mViewAbove.setCustomViewBehind(mViewBehind); + } + + public void setAboveView(View v, ViewGroup.LayoutParams p) { + mViewAbove.setContent(v, p); + mViewAbove.invalidate(); + mViewAbove.dataSetChanged(); + } + + public void setBehindView(View v) { + mViewBehind.setContent(v); + mViewBehind.invalidate(); + mViewBehind.dataSetChanged(); + } + + /** + * + * @param b Whether or not the SlidingMenu is in a static mode + * (i.e. nothing is moving and everything is showing) + */ + public void setStatic(boolean b) { + if (b) { + mViewAbove.setPagingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + mViewAbove.setPagingEnabled(true); + } + } + + /** + * Shows the behind view + */ + public void showBehind() { + mViewAbove.setCurrentItem(0); + } + + /** + * Shows the above view + */ + public void showAbove() { + mViewAbove.setCurrentItem(1); + } + + /** + * + * @return Whether or not the behind view is showing + */ + public boolean isBehindShowing() { + return mViewAbove.getCurrentItem() == 0; + } + + /** + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + /** + * + * @param i The margin on the right of the screen that the behind view scrolls to + */ + public void setBehindOffset(int i) { + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @param res The dimension resource to be set as the behind offset + */ + public void setBehindOffsetResource(int res) { + int i = (int) getContext().getResources().getDimension(res); + ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).setMargins(0, 0, i, 0); + } + + /** + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewAbove.getScrollScale(); + } + + /** + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + mViewAbove.setScrollScale(f); + } + +} \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e3/136a92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e3/136a92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..9465173781eaa7fc9ab0e191904f928ad1c0b8f4 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ#0V1dK=^FznmSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn1+PZ!4!j+x0n{{OdUW@bKIZ*t~9!x;yr|1&pm7#RS;1ieP?Kk11H z2?+-Ger=J9{IX`d2{ZSUyAFF~k44WnGFVV~q2hHg8$(d6=$w>Y|ILABGI+ZBxvX + + + + false + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e3/e0f3201785c2001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e3/e0f3201785c2001119baa706e9d70c26 new file mode 100644 index 000000000..8ab744a7c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e3/e0f3201785c2001119baa706e9d70c26 @@ -0,0 +1,1473 @@ +package com.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +public class CustomViewBehind extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + private boolean mEnabled = true; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + private int mDecorChildCount; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewBehind#SCROLL_STATE_IDLE + * @see CustomViewBehind#SCROLL_STATE_DRAGGING + * @see CustomViewBehind#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewBehind(Context context) { + super(context); + initCustomViewBehind(); + } + + public CustomViewBehind(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewBehind(); + } + + void initCustomViewBehind() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + setAdapter(new CustomPagerAdapter()); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mContent.position, mContent.object); + mAdapter.finishUpdate(this); + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + return 0; + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getScrollX() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + ViewGroup.LayoutParams params = getLayoutParams(); + return params.width; + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + private ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + public void setContent(View v) { + mAdapter.setBehind(v); + setBackgroundDrawable(v.getBackground()); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + int decorCount = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + if (lp.isDecor) { + decorCount++; + childLeft = getChildLeft(i); + int childWidth = child.getMeasuredWidth(); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } else if ((ii = infoForChild(child)) != null) { + childTop = paddingTop; + if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() + + "x" + child.getMeasuredHeight()); + // TODO PADDING! + childLeft = getChildLeft(i); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mDecorChildCount = decorCount; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. + if (mDecorChildCount > 0) { + final int scrollX = getScrollX(); + int paddingLeft = getPaddingLeft(); + int paddingRight = getPaddingRight(); + final int width = getWidth(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) continue; + + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + int childLeft = 0; + switch (hgrav) { + default: + childLeft = paddingLeft; + break; + case Gravity.LEFT: + childLeft = paddingLeft; + paddingLeft += child.getWidth(); + break; + case Gravity.CENTER_HORIZONTAL: + childLeft = Math.max((width - child.getMeasuredWidth()) / 2, + paddingLeft); + break; + case Gravity.RIGHT: + childLeft = width - paddingRight - child.getMeasuredWidth(); + paddingRight += child.getMeasuredWidth(); + break; + } + childLeft += scrollX; + + final int childOffset = childLeft - child.getLeft(); + if (childOffset != 0) { + child.offsetLeftAndRight(childOffset); + } + } + } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + // we don't want to steal touches from our children + return false; + } + + public boolean onTouchEvent(MotionEvent ev) { + // we don't want to handle touch events here + return false; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(0); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (width != 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e4/10e6ec4e4ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/10e6ec4e4ac3001119baa706e9d70c26 new file mode 100644 index 000000000..29cdb5af7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/10e6ec4e4ac3001119baa706e9d70c26 @@ -0,0 +1,121 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e4/520693ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/520693ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..ff54bbecd --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/520693ff24c3001119baa706e9d70c26 @@ -0,0 +1,24 @@ + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e4/70d9e47415c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/70d9e47415c3001119baa706e9d70c26 new file mode 100644 index 000000000..5b11b11e3 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/70d9e47415c3001119baa706e9d70c26 @@ -0,0 +1,1029 @@ +/* + * 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 static com.actionbarsherlock.ResourcesCompat.getResources_getBoolean; + +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.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.app.SherlockFragmentActivity; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +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.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; + +/** + * 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 SherlockFragmentActivity) { + trans = ((SherlockFragmentActivity)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/.metadata/.plugins/org.eclipse.core.resources/.history/e4/805d61b9f9c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/805d61b9f9c500111689feaa37e8ab14 new file mode 100644 index 000000000..2520d37ae --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e4/805d61b9f9c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.slidingmenu.lib.app.SlidingActivity; + +public class ExampleActivity extends SlidingFragmentActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20c2ed1b1dc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20c2ed1b1dc3001119baa706e9d70c26 new file mode 100644 index 000000000..c2767b4a4 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20c2ed1b1dc3001119baa706e9d70c26 @@ -0,0 +1,216 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + this.getWindow().requestFeature(Window.FEATURE_NO_TITLE); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ViewGroup layout = ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + layout.addView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20d4b2be28c500111b2a8b7f47e59881 b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20d4b2be28c500111b2a8b7f47e59881 new file mode 100644 index 000000000..710cd8cde --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/20d4b2be28c500111b2a8b7f47e59881 @@ -0,0 +1,36 @@ +package com.slidingmenu.lib; + +import java.util.HashMap; + +import android.content.Context; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.widget.LinearLayout; + +public class MenuScreen extends LinearLayout { + + private PreferenceScreen mPrefs; + private HashMap mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + cat.setTitle(title); + mCats.put(title, cat); + mPrefs.addPreference(cat); + } + + public void addItem(String title, String catKey) { + PreferenceCategory cat = mCats.get(catKey); + cat.addPreference(preference); + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e5/70ada704f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/70ada704f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..4984b812d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e5/70ada704f6c500111689feaa37e8ab14 @@ -0,0 +1,12 @@ +package com.slidingmenu.lib.app; + +import com.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + public SlidingMenu getSlidingMenu(); + + private boolean isStatic(); + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e6/81b789ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e6/81b789ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..f989197ad --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e6/81b789ff24c3001119baa706e9d70c26 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e6/d3af96ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e6/d3af96ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..5f1cd59df --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e6/d3af96ff24c3001119baa706e9d70c26 @@ -0,0 +1,721 @@ +/* + * 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.content.res.TypedArray; +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) { + //Check for theme-forced overflow action item + TypedArray a = context.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme); + boolean result = a.getBoolean(R.styleable.SherlockTheme_absForceOverflow, false); + a.recycle(); + if (result) { + return true; + } + + 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) { + 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); + } + } + + @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/.metadata/.plugins/org.eclipse.core.resources/.history/e7/126a92ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e7/126a92ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f3a5cbde81d4a69f473230431fbc2ef43d93f301 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ#0V1dK=^FznmSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn2LPZ!4!j+w~@_kK-jY;1gJZ)65y37#@YbYM!~yY#$);RA*zo(4&i m6B;jNx_Cd>(#$xWo$;KAD39oi<@P`m7(8A5T-G@yGywqAKq?vl literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e7/f07cf8c726c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e7/f07cf8c726c3001119baa706e9d70c26 new file mode 100644 index 000000000..f5f20d91b --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e7/f07cf8c726c3001119baa706e9d70c26 @@ -0,0 +1,215 @@ +package com.slidingmenu.lib; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.CustomViewAbove.LayoutParams; + +public class SlidingMenuActivity extends SherlockActivity { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// getWindow().requestFeature(Window.FEATURE_NO_TITLE); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + mMainLayout = super.findViewById(R.id.slidingmenulayout); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)this.getSherlock()).generateLayout(mainView); + getSherlock().setContentView(v); + mSlidingMenu.setAboveContent(mainView, params); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } +// mSlidingMenu.setBehindContent(v); + } + + private boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public int getBehindOffset() { + // TODO + return 0; + } + + public void setBehindOffset(int i) { + mSlidingMenu.setBehindOffset(i); + } + + public float getBehindScrollScale() { + // TODO + return 0; + } + + public void setBehindScrollScale(float f) { + mSlidingMenu.setBehindScrollScale(f); + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + // if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + // if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingMenuActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e8/20a470ea0cc3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/20a470ea0cc3001119baa706e9d70c26 new file mode 100644 index 000000000..7a91b2d5c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/20a470ea0cc3001119baa706e9d70c26 @@ -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.ActionBarSherlockCompat; +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.ActionBar.OnNavigationListener; +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; + + 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(); + 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/.metadata/.plugins/org.eclipse.core.resources/.history/e8/62da8bff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/62da8bff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ca8e9a2778f58deb3be0cba0d7af89400525896a GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^;y~=k!3HF){@Qy1DVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?cuyC{kcif|*Eb3_81S$-+V)J@yPBVWyvqG&GeYz~KYxJdw0eeyIoHJnOEfn# R{sUUY;OXk;vd$@?2>|r{LWckV literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e8/d06d700253c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/d06d700253c3001119baa706e9d70c26 new file mode 100644 index 000000000..ac3bdfeaa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/d06d700253c3001119baa706e9d70c26 @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e8/e3128dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/e8/e3128dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..743d00b6cd7e446c7badca9dd11d1579404569cc GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%KAtX)As)xyUQ!e~V8Fq8aW6aH z`M>?!MSK0VJ5DH+1)MRKpSquM-S5BdOIN+&sn~jE%jQNlsf-1UY_}X6mMgq#dKVMx ha^q%Y#@a>3az|3`-r6;1y%^A322WQ%mvv4FO#tkfF|q&v literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/e9/90fd3c83f4c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/e9/90fd3c83f4c500111689feaa37e8ab14 new file mode 100644 index 000000000..1f8e9c39c --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/e9/90fd3c83f4c500111689feaa37e8ab14 @@ -0,0 +1,41 @@ +package com.slidingmenu.example; + +import android.os.Bundle; +import android.view.View; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +public class ExampleActivity extends SlidingActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + setBehindContentView(R.layout.main2); + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width); + getSlidingMenu().setBehindScrollScale(0.5f); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + View v = getWindow().getDecorView(); + } + + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + toggle(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + this.getSupportMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/eb/02d28fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/eb/02d28fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..c4272978338a232aa445ed5190abab61afcedb16 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETEKe85kc@k8FK^^+Fc4rl_yt@$W?82D^ReIqPjo#d{bLmpkiN+x lnf&F6gB^EeSbfn>hW*nwPPt#_849$O!PC{xWt~$(697sdG9dr} literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/eb/401b89ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/eb/401b89ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..e8a2c080e --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/eb/401b89ff24c3001119baa706e9d70c26 @@ -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/.metadata/.plugins/org.eclipse.core.resources/.history/eb/60bc90ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/eb/60bc90ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6b3157985ea56214f20902e7854f630cf0513ad7 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETQcoAhkc@k8FK^^zcI0unxbj42 z@%PHs81cNrrDs&R`}mS?q)ZpDnc}&}A#--5>dP53cYgnN@8iE~W|ez(m3TTj;06C0 vR9@;$usQD^o~Q2-Eg&#Ke!|DE+S9qyz8u@<_Da1C=l}*!S3j3^P6 mCats; + + public MenuScreen(Context context) { + super(context); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + Preference p = new Preference(getContext()); + mPrefs = p.getPreferenceManager().createPreferenceScreen(getContext()); + } + + public void addCategory(String title) { + PreferenceCategory cat = new PreferenceCategory(getContext()); + mPrefs.addPreference(preference) + } + + public void addItem(String title, String cat) { + + } + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ec/01d28fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ec/01d28fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..6622cbad34409b2e09f69e305455482ee107baa6 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nETEKe85kc@k8FK-lVFc4sN{QB_B z&fog}EEk$2&*T)$|Ch61%h`96?xa8O-xitu^~t0=vn)PNZ(|U lO#br3!H&B!tiEU`L+e4N?emv^?*rP(;OXk;vd$@?2>`X4Gjad` literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ec/114c97ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ec/114c97ff24c3001119baa706e9d70c26 new file mode 100644 index 000000000..64fc4aeaa --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ec/114c97ff24c3001119baa706e9d70c26 @@ -0,0 +1,180 @@ +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) { + android.view.MenuItem[] nativeOutItems = new android.view.MenuItem[outSpecificItems.length]; + int 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]); + } + 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/.metadata/.plugins/org.eclipse.core.resources/.history/ec/f01dc6bbf8c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/ec/f01dc6bbf8c500111689feaa37e8ab14 new file mode 100644 index 000000000..204c100a8 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ec/f01dc6bbf8c500111689feaa37e8ab14 @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ed/90be72830ac3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ed/90be72830ac3001119baa706e9d70c26 new file mode 100644 index 000000000..dc7491f10 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ed/90be72830ac3001119baa706e9d70c26 @@ -0,0 +1,1874 @@ +package com.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.Comparator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.v4.os.ParcelableCompat; +import android.support.v4.os.ParcelableCompatCreatorCallbacks; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +public class CustomViewAbove extends ViewGroup { + private static final String TAG = "CustomViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private ItemInfo mWindow; + private ItemInfo mContent; + + private CustomPagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mTopPageBounds; + private int mBottomPageBounds; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private int mFlingDistance; + + private boolean mFirstLayout = true; + private boolean mCalledSuper; + + private boolean mLastTouchAllowed = false; + private int mSlidingMenuThreshold = 30; + private CustomViewBehind mCustomViewBehind; + private boolean mEnabled = true; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + * @see CustomViewAbove#SCROLL_STATE_IDLE + * @see CustomViewAbove#SCROLL_STATE_DRAGGING + * @see CustomViewAbove#SCROLL_STATE_SETTLING + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + + public void onPageSelected(int position) { + // This space for rent + } + + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(CustomPagerAdapter oldAdapter, CustomPagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor {} + + public CustomViewAbove(Context context) { + super(context); + initCustomViewPager(); + } + + public CustomViewAbove(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewPager(); + } + + void initCustomViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + setAdapter(new CustomPagerAdapter()); + setTransparentWindow(); + + final float density = context.getResources().getDisplayMetrics().density; + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a CustomPagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + private void setAdapter(CustomPagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + mAdapter.destroyItem(this, mWindow.position, mWindow.object); + mAdapter.destroyItem(this, mContent.position, mWindow.object); + mAdapter.finishUpdate(this); + mWindow = null; + mContent = null; + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final CustomPagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered CustomPagerAdapter + */ + public CustomPagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mWindow != null && mContent != null) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + if (item > 0 && item < getItems().size()) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + mWindow.scrolling = true; + mContent.scrolling = true; + } + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + populate(); + // final int destX = (getWidth() + mPageMargin) * item; + // TODO + final int destX = getChildLeft(mCurItem); + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + public int getDestScrollX() { + if (isMenuOpen()) { + return getBehindWidth(); + } else { + return 0; + } + } + + public int getChildLeft(int i) { + if (i <= 0) return 0; + return getChildWidth(i-1) + getChildLeft(i-1); + } + + public int getChildRight(int i) { + return getChildLeft(i) + getChildWidth(i); + } + + public boolean isMenuOpen() { + return getCurrentItem() == 0; + } + + public int getCustomWidth() { + int i = isMenuOpen()? 0 : 1; + return getChildWidth(i); + } + + public int getChildWidth(int i) { + if (i <= 0) { + return getBehindWidth(); + } else { + return getChildAt(i).getMeasuredWidth(); + } + } + + public int getBehindWidth() { + if (mCustomViewBehind == null) { + return 0; + } else { + return mCustomViewBehind.getWidth(); + } + // float homeWidth = getContext().getResources().getDimension(R.dimen.actionbar_home_width); + // return getWidth() - (int)homeWidth; + } + + public boolean isPagingEnabled() { + return mEnabled; + } + + public void setPagingEnabled(boolean b) { + mEnabled = b; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final int width = getCustomWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / (width + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + // TODO set custom duration! + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + ArrayList getItems() { + ArrayList mItems = new ArrayList(); + if (mWindow != null) { + mItems.add(mWindow); + } + if (mContent != null) { + mItems.add(mContent); + } + return mItems; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + boolean needPopulate = getItems().size() < mAdapter.getCount(); + int newCurrItem = -1; + + boolean isUpdating = false; + // TODO + if (mWindow != null) { + + } + if (mContent != null) { + + } + ArrayList items = getItems(); + for (int i = 0; i < items.size(); i++) { + final ItemInfo ii = items.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == CustomPagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == CustomPagerAdapter.POSITION_NONE) { + items.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + if (newCurrItem >= 0) { + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + private void setTransparentWindow() { + View v = new View(getContext()); + v.setBackgroundColor(android.R.color.transparent); + mAdapter.setBehind(v); + + ItemInfo ii = new ItemInfo(); + ii.position = 0; + ii.object = mAdapter.instantiateItem(this, 0); + mWindow = ii; + + mAdapter.notifyDataSetChanged(); + } + + public void setContent(View v, ViewGroup.LayoutParams params) { + mAdapter.setContent(v, params); + + ItemInfo ii = new ItemInfo(); + ii.position = 1; + ii.object = mAdapter.instantiateItem(this, 1); + mContent = ii; + + mAdapter.notifyDataSetChanged(); + setCurrentItem(1); + } + + public void setCustomViewBehind(CustomViewBehind cvb) { + mCustomViewBehind = cvb; + } + + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + if (mAdapter.isViewFromObject(child, mWindow.object)) { + return mWindow; + } else if (mAdapter.isViewFromObject(child, mContent.object)) { + return mContent; + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent=child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View)parent; + } + return infoForChild(child); + } + + + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, or internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } + } + } + } + + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (w != oldw) { + recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { + final int widthWithMargin = width + margin; + if (oldWidth > 0) { + final int oldScrollPos = getDestScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, getChildLeft(mCurItem), 0, newDuration); + } + } else { + int scrollPos = getChildLeft(mCurItem); + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + int height = b - t; + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + int childLeft = 0; + int childTop = 0; + childLeft = getChildLeft(i); + int childWidth = getChildWidth(i); + child.layout(childLeft, childTop, + childLeft + childWidth, + childTop + child.getMeasuredHeight()); + } + } + mTopPageBounds = paddingTop; + mBottomPageBounds = height - paddingBottom; + mFirstLayout = false; + } + + + public void computeScroll() { + if (DEBUG) Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + // TODO + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + mCalledSuper = false; + onPageScrolled(position, offset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. +// if (mDecorChildCount > 0) { +// final int scrollX = getScrollX(); +// int paddingLeft = getPaddingLeft(); +// int paddingRight = getPaddingRight(); +// final int width = getWidth(); +// final int childCount = getChildCount(); +// for (int i = 0; i < childCount; i++) { +// final View child = getChildAt(i); +// final LayoutParams lp = (LayoutParams) child.getLayoutParams(); +// if (!lp.isDecor) continue; +// +// final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; +// int childLeft = 0; +// switch (hgrav) { +// default: +// childLeft = paddingLeft; +// break; +// case Gravity.LEFT: +// childLeft = paddingLeft; +// paddingLeft += child.getWidth(); +// break; +// case Gravity.CENTER_HORIZONTAL: +// childLeft = Math.max((width - child.getMeasuredWidth()) / 2, +// paddingLeft); +// break; +// case Gravity.RIGHT: +// childLeft = width - paddingRight - child.getMeasuredWidth(); +// paddingRight += child.getMeasuredWidth(); +// break; +// } +// childLeft += scrollX; +// +// final int childOffset = childLeft - child.getLeft(); +// if (childOffset != 0) { +// child.offsetLeftAndRight(childOffset); +// } +// } +// } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + mCalledSuper = true; + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + if (mWindow != null && mWindow.scrolling) { + needPopulate = true; + mWindow.scrolling = false; + } + if (mContent != null && mContent.scrolling) { + needPopulate = true; + mContent.scrolling = false; + } + if (needPopulate) { + populate(); + } + } + + private boolean thisTouchAllowed(float x) { + if (isMenuOpen()) { + return x >= getBehindWidth() && x <= getWidth(); + } else { + return x >= 0 && x <= mSlidingMenuThreshold; + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + /* + * This method JUST determines whether we want to intercept the motion. + * If we return true, onMotionEvent will be called and we do the actual + * scrolling there. + */ + + if (!mEnabled) { + return false; + } + + if (!thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + // Always take care of the touch gesture being complete. + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + // Release the drag. + if (DEBUG) Log.v(TAG, "Intercept done!"); + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + return false; + } + + // Nothing more to do here if we have decided whether or not we + // are dragging. + if (action != MotionEvent.ACTION_DOWN) { + if (mIsBeingDragged) { + if (DEBUG) Log.v(TAG, "Intercept returning true!"); + return true; + } + if (mIsUnableToDrag) { + if (DEBUG) Log.v(TAG, "Intercept returning false!"); + return false; + } + } + + switch (action) { + case MotionEvent.ACTION_MOVE: { + /* + * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check + * whether the user has moved far enough from his original down touch. + */ + + /* + * Locally do absolute value. mLastMotionY is set to the y value + * of the down event. + */ + final int activePointerId = mActivePointerId; + if (activePointerId == INVALID_POINTER) { + // If we don't have a valid id, the touch down wasn't on content. + break; + } + + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float dx = x - mLastMotionX; + final float xDiff = Math.abs(dx); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (canScroll(this, false, (int) dx, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mInitialMotionX = mLastMotionX = x; + mLastMotionY = y; + return false; + } + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else { + if (yDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + + if (mScrollState == SCROLL_STATE_SETTLING) { + // Let the user 'catch' the pager as it animates. + mIsBeingDragged = true; + mIsUnableToDrag = false; + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(); + mIsBeingDragged = false; + mIsUnableToDrag = false; + } + + if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (!mIsBeingDragged) { + // Track the velocity as long as we aren't dragging. + // Once we start a real drag we will track in onTouchEvent. + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + } + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + + public boolean onTouchEvent(MotionEvent ev) { + if (!mEnabled) { + return false; + } + + if (!mLastTouchAllowed && !thisTouchAllowed(ev.getX())) { + return false; + } + + final int action = ev.getAction(); + + if (action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_POINTER_UP || + action == MotionEvent.ACTION_CANCEL || + action == MotionEvent.ACTION_OUTSIDE) { + mLastTouchAllowed = false; + } else { + mLastTouchAllowed = true; + } + + if (action == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + } + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + // TODO + final float leftBound = 0; + final float rightBound = getBehindWidth(); + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + // scrollX = getChildWidth(mCurItem); + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + pageScrolled((int) scrollX); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int widthWithMargin = getChildWidth(mCurItem) + mPageMargin; + final int scrollX = getScrollX(); + final int currentPage = scrollX / widthWithMargin; + final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin; + final int activePointerIndex = + MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final int totalDelta = (int) (x - mInitialMotionX); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + return true; + } + + private float mScrollScale; + + public void setScrollScale(float f) { + if (f >= 0 && f <= 1) { + mScrollScale = f; + } + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + if (mCustomViewBehind != null && mEnabled) { + mCustomViewBehind.scrollTo((int)(x*mScrollScale), y); +// mCustomViewBehind.scrollTo(x*mScrollScale, y); + } + } + + private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { + int targetPage; + if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage : currentPage + 1; + } else { + targetPage = (int) (currentPage + pageOffset + 0.5f); + } + return targetPage; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getDestScrollX(); + final int width = getChildWidth(mCurItem); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, mTopPageBounds, left + mPageMargin, + mBottomPageBounds); + mMarginDrawable.draw(canvas); + } + } + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + // if (x + scrollX >= getChildLeft(i) && x + scrollX < getChildRight(i) && + // y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + // canScroll(child, true, dx, x + scrollX - getChildLeft(i), + // y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a CustomViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // CustomViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + private class PagerObserver extends DataSetObserver { + + public void onChanged() { + dataSetChanged(); + } + + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * CustomViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Where to position the view page within the overall CustomViewPager + * container; constants are defined in {@link android.view.Gravity}. + */ + public int gravity; + + public LayoutParams() { + this(-1); + } + + public LayoutParams(int customWidth) { + super(FILL_PARENT, FILL_PARENT); + if (customWidth >= 0) { + width = customWidth; + } + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.NO_GRAVITY); + a.recycle(); + } + } +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ed/d01e0b5415c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ed/d01e0b5415c3001119baa706e9d70c26 new file mode 100644 index 000000000..f80a79c3d --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ed/d01e0b5415c3001119baa706e9d70c26 @@ -0,0 +1,255 @@ +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.ActionBarSherlockCompat; +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 = new ActionBarSherlockCompat(this, ActionBarSherlock.FLAG_DELEGATE); +// 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 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/.metadata/.plugins/org.eclipse.core.resources/.history/ee/c2358fff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ee/c2358fff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..f0cecd183ae8bff87bff9dcff6841468d33145cf GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!3HFsSlX9@1d5$JLpXq-h9ji|$mcBZh%9Dc z;O+!rM)Q-W*8&ACJY5_^IA+G4Imp@IAi#1kNN+LcIT4=>=UW!n`aACInYB!EW!u3$ rIYDzn*o$v%D|qmWd&mA1`&tG?86nH1GYjqj&0z3!^>bP0l+XkKX|61& literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ef/101b573952c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ef/101b573952c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..cae1778f439bf96bfd43d73c8756c6deb4a71ba6 GIT binary patch literal 952 zcmaJ=J#W)M7`9Xt(n>*{P+>raE0`L8rH*4OCZw@Ljc^pDkq8?X`;u6xea5~JClj!- zG4c~&fE6JmU|?b34>0f-7-0+NG)@@^md3N>_^Paa`cM3aKcNm5#SjR?(?pt(S z%;)I;+xuUy>2`&fJ#vBvWC|n1)Lq<1!1Cb`br5uCkG`TRC9z(&M|$=>&A~ngQw*2* zA!Rd6wU&g?86yJvXy^qx`}4ym7I?1C-j{8`4jX9X9nT|lGH-RA`Pfliwss3t6O9V^ zh(M6|r$MYGI=j@>=sCUSS+InVvCf_a)wA26fg=QDPAED;Spa2`6HAARq8tE85CvY4 zcu^{fidK>|K>(|drQRZUpmmJq$``eCc0@?1@%(f;<)$SLM?+pzRW;R+q#{KW<5@sp zQVin#Ou<006L}%=Z~#(8*vAv1vozAP6#Q^48^o(J(Sq>_40(|g(v&iwZT}zY`)hPe zI_Ny!e+tLlS%~-!it!|JXyXR^sjEC? z)~p~VFmRA%=qy#>JkQmRXpJjUrEHcASrkp7UM`u9rm4t+B8sZq$hZb}CO!&C#&yrR z%0_NF3VujE8z}M~Bexl0A1qVWyv?y3Zq!?G-OaJc8@W6UhEE&&SEI8lIz8!eJ+{ parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + + + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ef/60b92661f6c500111689feaa37e8ab14 b/.metadata/.plugins/org.eclipse.core.resources/.history/ef/60b92661f6c500111689feaa37e8ab14 new file mode 100644 index 000000000..29fb8d8d2 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.history/ef/60b92661f6c500111689feaa37e8ab14 @@ -0,0 +1,195 @@ +package com.slidingmenu.lib.app; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.actionbarsherlock.ActionBarSherlockCompat; +import com.actionbarsherlock.app.SherlockActivity; +import com.slidingmenu.lib.MenuScreen; +import com.slidingmenu.lib.R; +import com.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends SherlockActivity implements SlidingActivityBase { + + private SlidingMenu mSlidingMenu; + private View mMainLayout; + private MenuScreen mMenuScreen; + private boolean mContentViewCalled = true; + private boolean mBehindContentViewCalled = true; + private SlidingMenuList mMenuList; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + super.setContentView(R.layout.slidingmenumain); + mSlidingMenu = (SlidingMenu) super.findViewById(R.id.slidingmenulayout); + // generate the ActionBar inside an arbitrary RelativeLayout + RelativeLayout mainView = new RelativeLayout(this); + ((ActionBarSherlockCompat)getSherlock()).installDecor(mainView); + mSlidingMenu.setAboveView(mainView, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mMainLayout = super.findViewById(R.id.slidingmenulayout); +// mMenuScreen = new MenuScreen(this, new Preference(this).getPreferenceManager()); +// setBehindContentView(mMenuScreen); + } + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (!mContentViewCalled || !mBehindContentViewCalled) { + throw new IllegalStateException("Both setContentView and " + + "setBehindContentView must be called in onCreate."); + } + mSlidingMenu.setStatic(isStatic()); + } + + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + public void setContentView(View v) { + setContentView(v, null); + } + + public void setContentView(View v, LayoutParams params) { + if (!mContentViewCalled) { + mContentViewCalled = true; + } + getSherlock().setContentView(v); + } + + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindContentView(View v) { + setBehindContentView(v, null); + } + + public void setBehindContentView(View v, LayoutParams params) { + if (!mBehindContentViewCalled) { + mBehindContentViewCalled = true; + } + mSlidingMenu.setBehindView(v); + } + + public boolean isStatic() { + return mMainLayout instanceof LinearLayout; + } + + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + @Override + public View findViewById(int id) { + return mSlidingMenu.findViewById(id); + } + + public void toggle() { + // if (isStatic()) return; + if (mSlidingMenu.isBehindShowing()) { + showAbove(); + } else { + showBehind(); + } + } + + public void showAbove() { + if (isStatic()) return; + mSlidingMenu.showAbove(); + } + + public void showBehind() { + if (isStatic()) return; + mSlidingMenu.showBehind(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isBehindShowing()) { + showAbove(); + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + public void addMenuListItem(MenuListItem mli) { + mMenuList.add(mli); + } + + public static class SlidingMenuList extends ListView { + public SlidingMenuList(final Context context) { + super(context); + setAdapter(new SlidingMenuListAdapter(context)); + setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, + long id) { + OnClickListener listener = ((SlidingMenuListAdapter)getAdapter()).getItem(position).mListener; + if (listener != null) listener.onClick(view); + } + }); + } + public void add(MenuListItem mli) { + ((SlidingMenuListAdapter)getAdapter()).add(mli); + } + } + + public static class SlidingMenuListAdapter extends ArrayAdapter { + + public SlidingMenuListAdapter(Context context) { + super(context, 0); + } + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView != null) { + v = convertView; + } else { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + v = inflater.inflate(R.layout.slidingmenurow, null); + } + MenuListItem item = getItem(position); + ImageView icon = (ImageView) v.findViewById(R.id.slidingmenurowicon); + icon.setImageDrawable(item.mIcon); + TextView title = (TextView) v.findViewById(R.id.slidingmenurowtitle); + title.setText(item.mTitle); + return v; + } + } + + public class MenuListItem { + private Drawable mIcon; + private String mTitle; + private OnClickListener mListener; + public MenuListItem(String title) { + mTitle = title; + } + public void setTitle(String title) { + mTitle = title; + } + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + public View toListViewRow() { + View v = SlidingActivity.this.getLayoutInflater().inflate(R.layout.slidingmenurow, null); + ((TextView)v.findViewById(R.id.slidingmenurowtitle)).setText(mTitle); + ((ImageView)v.findViewById(R.id.slidingmenurowicon)).setImageDrawable(mIcon); + return v; + } + } + +} diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/ef/d0cd91ff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/ef/d0cd91ff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..345f5d3067c1b5a2b13f7234238468e8083e75e8 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr?*8<0#p>+uXou@pObhHwBu4M$1`kk47*5n0T@ zz}*SLjOHg#uLTMQc)B=-SoFS~;>gutz{8S$H2ll||1$b2>+ab^8r zChoU9-sVBr1cr+EHAcpdxgPN?*fw!WN@w!F_di=AUe22-xp-2_jNr43yl#?i1$i|o QK(iS + + + + + + + + + + + + diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f/0046de3c52c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f/0046de3c52c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..47b27d1f90108f132fd7a243e43e3a69f2104197 GIT binary patch literal 1768 zcmaJ?c~BEq9Nu^ULL(vtxoWpTl+E6TpCPR z#}H5iDlR0GN9L-bxZId{Nv=W?Bqgj|0dll#OaO*ZF{p*pl^V7-m@uKs#^%;#G69@` zpo(C^KSd=9VnHsVhCl|1LX=RL6p%?JQRx9J7Hc_3qfjYi3XM#q5veRToyMk6z{!Vz zWm8L2*+O3UWG*ZUCdg1!#U_)pv$ILrbP}RYBU6Kdf~*=e8WBSfH91ODtR*Tn-ct%Z zNF!0pRj3?Mf>uTGW+W30CSaBRvjtc+EvwW_wh3z(Su0kNsU(VZOH)9B;Qyg8JdM_% zLg-z+|0%4A&rv~SA*4Yv)e`LBQoXIIRBWyq5~GMZ9zoKlx)>`%P(&j`R3JBw0Sd$t zxzZX>-~|G9lv0C=l@ch57fiquNOHN9O{WIZ!uSk2pU$IGseDQ(lg{Uc^H~fEi%Jb* zaHqIDM3M&fp?X2So zOU^|)@vFhmReWBV*EVB9UTo`!+kFXrE{+7PkfZJ0(o{T9W$Wll91nTh?N7K+mg3U= ziC=<~A70pcbbF$6qhp_ml3r@~t<7NgVJmq_efgiy%F9{9m!gcqA^wD z=-A2LqE7tTTW+T8#Y;;n<^xH2^@Tsbaq?fgdYPs9RN1cGPm33E?;uPdb~$it(XOx! zvpRQjSyg`HF-~_&bU7TGyG0EZH7|VTXy{YXWXMQS^^2YaZf87W(JeY;XgN3~JIflDzH3+3L#ClW~$u zn;tK1H35~-y4TTi&X-dStTk-d$u9 zbi$@G@5s8KvFI3M>8vJ}e?iZ=pN{IZl0BPB5B%EZapOvDSNR$O&|j0h>B_41LG7(x zdV#qy7RdPBAv$bbl|oooKF`viH)OQj*M)l~I5_5c&@XaY-W$L~D z2fnUu10`qnZ#6JGIX;2;W3JabqUQ|U4m?q{??uI(JBN;ZFl}h7y(_Md&!Yff^~gO2 Soh!Bed!qO;ywhPR1%Cs?x~41u literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.core.resources/.history/f/03618dff24c3001119baa706e9d70c26 b/.metadata/.plugins/org.eclipse.core.resources/.history/f/03618dff24c3001119baa706e9d70c26 new file mode 100644 index 0000000000000000000000000000000000000000..ad980b13fc8142f3f8ebeb7e2e55f21182f759e5 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%L7py-As)w*fBgS%&%9ECfoo 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. + * + *

`9G%u$7y<*ztZe2*?dYmiOy$sJn5rj}B15*W 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 z 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 MW5&4Ey!-F^KaZ*q!2kdN literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.jdt.core/2040064081.index b/.metadata/.plugins/org.eclipse.jdt.core/2040064081.index new file mode 100644 index 0000000000000000000000000000000000000000..15562f0daf353f85bae6690534ed0f0facca6d9e GIT binary patch literal 52626 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 dHYU0s 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 h%#iB03}9yYO zx(6bE@jxwMVr_mm1DVHS{rL-GfYyTgbmoMPui?`}OPZ;_n>y}9htFMaOx>?b>QCv& zbu?E+>$-)FBJVwwsBE^&DGk#w^BeeN?9GGFKOcvl>a1(%elv!#z3&%1lDiTo;g>jR zc%5-W)xwVpn~ z*l96itzuPvVfX^?9Ip-SOD=z=s|k-1#4~tSF4X5gkopGITnD$%iBeI>d=tqu-xgH< UKvUu~Z;@4nX0ge5t}Cri58XicsQ>@~ literal 0 HcmV?d00001 diff --git a/.metadata/.plugins/org.eclipse.jdt.core/3058661946.index b/.metadata/.plugins/org.eclipse.jdt.core/3058661946.index new file mode 100644 index 0000000000000000000000000000000000000000..dc3158bb8a3973b5bd3f43e2c695a97410763e1b GIT binary patch literal 1494519 zcmb5Xd4OD5S@(a}>a}`bvS*U?3^NQv&t!>soa((nFHYq?4HeQLI$mbQh_vYO1P} zG>Qu#;=b=IDvG;;;;W*#fcpxH`@SzIil~6V`}scS+*{R2^!@$*Ncz^fXMN7IKhHTg zm|i)5^3+pzJ#p&d+REzryB>PxL&u*T%>C-`2S+N+TDw)REuO11>sPZ*cVR1QZ`M1V zdaL=&YNOKW>@NkSm#(*4+glT*AQ(rvXz_}gw*cK922yX|3qUTL)& z{7tK^MoR^0t-hHxsW8y4+^Ae>WRwkFZC9#YM&UWC*LYcKcC+=YJvKnKtyY7+c~xpu zc3RtAo)Ws)rdnFx+N^9*FtF9wZdV!|9%K4dzFx0pi%b25Yp(Di##(7!Z86r-)^@YoSzNk8$IO=6Dp=a?Ze-1Fy{hF; zF{~@zQwnBxy;@>@*BR_?R(mn)Y_*!5j7kH5y23&aQ@mVhG_F*t*LW_S-tKOSi_D5^$zQf~o$|PG+5IyMAaSNK|EVG8jIeb#JuV*G{$DlciwKYSYiLb9t*)>1Jo^ zoo?35G|RngY(;%8SDMwVk=2SpfY4Dk)Lt$w*;A{%kU!*I>;sPb*c(8@-emiRg3A3jrv`%Q3+)!G>+U?kSXt*xt5M4+ z9=`tu`dDO*}Js`s%Tm#D(wX~)e9A--kCF? zp93|YsOQL)&v(xl+f%t-UpL57Grm;0vX^z|6=vxjqDq7$Ghp_kqB0()JccZs%Qjo> z9U9#A-ZF{^@$mnxlW2Zw`+?Pe1KSlZh1b&m}P10Jn;OjHee z4$9>qX;j*qV}rpsa64JAG+OI!>*je4X^+$^og9D5rQq(Zt%mSj8J{5tJku& zpW13uMc`Ksx&vCph~dNF>2_ru=FnxHGp!pal>M&msZw}|3Evz&<-3nB0i!Nw|EgN2|T+eE@0qj-4zq?Pgvr28by}fy*v#{Fi z{aOZS*YYU~m#93K&+P3t=6Y7k+iKpl9WkP)7$yb}<*d5` zc51ea4-|H9(z#Z%4wrJQd;u;4Bie2l9JI?YhpvY`i$4HCu5VY`1^DvcXIs^4KyhZZ znU|cpS?~6`8XXMwovmy)s~cH62j;>`wbi6b{S|NnL;00%wrTq|7Q{du%vGXkUdX|^4|I@8*{c4V=#)`5w95v`;yV~RnS+fS6 zh&MF53%4;uSl#ey^K`vg?`&i>jZN3(c5A&2`8kZFmqTk=rCr^~XT0heYrbU%#)5&9 z^^RnzdJw-8zKIxsd}{KCUPj;veG51O%en>g#l>#HeA<;S*Uzm_5DSXt)>Z*7bn|83%zt-)!|t2jQHx>0|%eMx~wAF0`|&Svy0Nb$T5lvS)78 zYwKBe5gz!YJ)LQFx{zM-L_NC!8RbyfKNyr?lGp1s%|hTnwVA(y{OGn?-HpW)`P0(z z+7?(_LdL3Qb(Hh1?rC(Jo>IWO{T-?r2R#F;X=Lq% zC($&Z@b-G=UM<6wGS^^sFc_3@5!pi5hflP5s8%}g2!~$_p5z?QP!p<^;g4I|?**|2 z(W%(0sW_(nfEV{&Y4!1=)#imZib{J&4R2wQ0yC4IY;B@wvG9U-0Hp9Z_?Vn`s>T6> zi`#qFbfLbLX%0`e>wrW|ntvq*pbwrVS986|$;YhC(yfYH3i58yV05msrDsZ84K{=4 z-nI8yJQ#4pwbhAtGz>{q_Hqb|7+HQARZ3Eh1aL92MQ&_H6su_~RaVEFh!LxFH zpYQA)>i5eV$McW&*bt8~{F^@$=a2#Q<&75Xz+@C<$=XKihL+F9>^+6x>+UQFVl@y` zh~#uDw3vW@gKQX>+G+-qiHs+LN}FN^(O{{gHD<( zoNh6^p8b*>SD7D_U~|QrTa7H&nl(=vPoLZFig8<;n_b&HR(-I*3urgjjf#P(FnS?t z*ITuERRqWH!#ODkF(J35Mx%A3PYYKSCsCYAx3;~$4)cQ)?yxP2#TRN)o3`BHD4`V%+AaFx=1AetU8gJyU*Bp3CrTcVbsBCv~ z#tfhaLHBc&Zgqo|jBjn4!Ys{Jyp>i9Jus~JvB z#}|1wa5}5VP~vg?7Oe+?Q9fI_BICv(0tF)%kYAWv8WUD|5JvOA50CIan9Foc?l#US zpi#*|0jeJDZm`wfW@e#N#ShcxH5#gUFvHYM-XO(F!4c0V{^z+M9fIi*B&%7a^gD>u zv6TbgXS6fS(hfpI64hCSTfk4$)LL$|I;l}LgO?#UNt&HJi}file4 zvaEJfZ-pgLLH`C&VPN&j6-`^LY^_=W6Wf&T*MdaeorT*V#!}Kt8`)+CnQDk(VOecS zUITtjKDF7%8)H;;vi9I$a9<6UdSrb7`4zL7B z!n!}Pef6r$%L&KB9JY#@nNoyVJP=H@TOARYEGrx0*g#Nn9GbU@24$gpS710d0pjY_ z6B3g>3!Rtc$69rOu)rcE0vrFs>ZA_xfLV@l2O%JS#ts8|sJ~bL7S$jQ$-iLb=;MeHd z<7W%TH8ma#b}OJ1-A|4OQ=OONF3A?D!k?upaP#0fxg09CXm=%ZsfZ$qPMst=G#>0f z!6vODBO2SAsGvDWFUr1bz!oy{A{Ic^Z=Nx-Q#fzzKBz% z-s~2`P?|at@qIW|YK7BKg|ne4LfeNCsaeh`ow|fT zwr=tP??S6kkB9jyjv?_)qteCt`bJmHN7vYk%sdLMCaiRdiTPdaI3(#%T4u)1=OeyB z!Qcf1#})XxxUcKX%?NHH^<{W_OTGsU$sh+DA)UI37K8qKF6&l=xsKJSg^VZ90kWC^ zj`}<<*^87}eANAgqKD4bue4EZvJNC3?oe`Y6(}+lnHH?wSIt-djIm${GH|NQ{jzzR z>ymFYOfSGOqzfWM0KndXAa1v=>9@_5B}}g}5PDb5*bOaDv~Fr;m_4Wz+EsRQADm^Q zUPTgI$A$Y8_RuCK;ezZ!Fhi1k_C&plw{$`B6p_(E0|J?mUWtS%18O$oo+cJnP3!Kc zEyd-F**fE#%&PR)o*%-P*{Hx1Cvm%;L)Z8E8-^0-rol?fh|6{b1SvPKS30O6>!!Z# z83=}+5W3xDW*QSNmPp9VL8sOWLZ;*x7br4f0?74FU*l*3o$NxTyKxF$UhRsbG7+Z4 z%ds|$xA$&xB1lf+S;ECQP{&h>F2`6yc!ynglcON|<`p=;7QmE8RyNTM98|P4Anu)o zo}G)EOQPWO%i0$)Xi(~2kxjv#g~RMiF7?{1)vwVg^yl|jJO@WdvYY(_xsfqB8Y zgJT7=qh_-WoXaX5sAUQy0Xyk&=w{Y%V5Pf}r&{eCJ8kb-8^z&iDwe^E_DRIFp)DGk z4BCDa;OAi87|4uW1iY0-4rO{6^qV3lcgzx)uk}12>;h?yKZRHbY z^g%&ZJ%d;SerbAq(e`zrBac%xA1Lwec!s+R^--m4;hKh?A^duQc>m8>_zb+Qzng=TwVfKSEdVXyVbV1->*hLQ$vdS))c7 z=0X#f0yUi6W-djzVSWrk$h~oDzumdAc)5f7QOYk$5p%-wa=0S<&bzFT2g4M5i<9!f zQ_b3zB$yh&X%KQOn;*GzO^@E=4t!75Ws7WP*!j4zDhU+WRFwg4^^B@cq3#;>h&<-lX zcVgbC1sJ>e+ohE8w z86#VrHITd^zwi1ugn2znHojRoP{t~_{0CuY?+UX^+U z%MpuTN)+nR@OG^ZnoBQ$@F#+W%PA)kx+c;@K2fKYNi5QLmYEfNNMHU!z+5wR18puyI!2*Oz zY0d0uD0uu9z50+J59MUUyzOrLs5xpwSPxmd*9X|EeR!rf*L%cFgb_I0R_xSy;@0yx zkTCJ{MHKNU&|gu)qZbKKcFi@`ZZ*6SkV93}*U}`U^A7;YE>;s_KW7qb!y%T~tX&{o z0OYvc1818B_Fvk-)!szxnszL^fu0^!Tw6XP@L+#MxO(;Gq647miMZnxE8jxa9l(={ zv}20SOxT6b3;Tl7sis7xrpo+|5t8VfXc0CL#wyAy7QL&DeENeJ@=^dhlJYcr;8gQ^ zz1?bB3=W3|rool}xdTLJ(ZPLmz*3LCe7n*BIpo*;|2phoumHlrr2hBuU{S?rlK)Ki z?kDQ)?*DT@Di;j}9>PQiI=xmhme4{a${l^lhXh`fGuwhir?KzHb`<=xo8aMqm*qT; z^^;cC#-JJRZY`ecDimV+icCZ=gJ6P2V&lU^m@NL!(}1ie^mmx+JW_Bm$7^{VJs%@* zHw-nRkE1kpu=EB`ZdA7T7Uxpo$A z@im=@p-=3XdgGFM-|JH|G#JQ;vV~vLRIoj66d9gl>@<#_+`-LslXmOo&gej}Z*A@D zGFFp|XJ#(A~^UEoE|q+rkT4O~_5%@$_T51moQ zv0N4Xf_@tQ@AqW^{5B79rUp!9{01AjC}zr{@!uij$8b|9a^MwnfO7arDuKnlK%j+3 zmKy7dkZf#1$0O!cUaoHuYUk$wD#y9?%`T6iQoVhn-pSlcSTz3TE-FQXm)>O~;?GHm zzjzBR6=}iZL5kOb*-9iyG!emwX_mG+LSgOM*72=Hy}5AQhbyV#36!1_@c>HPe(>Og zVqeO`ZoNn|6kBa(4XlkqbGdsgC>PqM5zmzGazXMn%i0=;H7PS^>S}e-Nxy=I0QSiF zT87iD(}6kQHNkTwg#zL_b~TTEE-a(uceB2Vx#m4TPSCHZ7ZVgH3>s46K z@Z|o?8)rP_PTRfYS2?_4?W1BF>16rf5<=6M|Au_#xDqk$_LiAP5U@6U&6%xV!J}vU zMsci`p~K6}C6Sk$Re1jqPs6=TEFp;EBxt*ePUE+b-;y;2WD3lksMKI^mPQ8O;~UtEwdk%QI4D&sYnCUSj=Rad^a3|IrW}WvyZ9o z|3{$fJ{RcnZkI8$X^P&2*q68KGLq+=gG5OiE;4Mq0IS(~v$UIr0!#{bT-IjYB$oA( zlb)m73%DkiGY zB_Zg`QgZ|bA@1o8Zw}(%>&j)d;DF_Fc5+GYb-RftHg}iHqYDvhvconrLWI?8bUb>g zbuDW?SuAsZFKR#_=4^#{Q86#74?ZCmI7%1K!%7BmCJMjqQko9jc5$^yc+j+*-5N83 z)V%%FF|>t09mFN=b9fe)H?rzAP#SI47fnwfS}ZYAGP+Xv~tG96uIu`Z)D~rv&YGONJIrOKUi@ zvnCvP>Y}%#dMgs7)^5~6RYB^~jh2C*eCSD~H)ZX`CFOeBmV;;`f(~A5B5<9laxmU* z-GEasVDMZcv*y~~GM!ms8yrsFg?%gsu3RB%2b)1rTv&oV!XdKG{ifKfCycCeUT=v^ zq3(mlt6tv9mJfg9X1k@wqCncLfBrOh?JW2!6671hSnv<^T@8w#Fdpct&XvIjY0N0K1w>R zrbIx|>3lMkkTS!Kv!vCsxQ4uGVzYB{x>mcL1p$)>=lSaNWN$oGAfnuBjHzkgH zdl?X74GL+*4GDc6>><|rdK-&Gva{eiM^V6yp7SlI{T`IEO?=^4pD$!9I!5qvsvpNi z{J|hGP{D$EPDtzEDQwWh7qde zCVwB`^AWlG@HC02x9=Ma<~j>YJvbFvLie*m0ffJvP(r;Oz zajnO~MHG|_iTkjfvRlxW_5r0MhHqzZ^s#X14@2&}Qwbw$i>08~^R zZ5nUQlk8qXq~%AmCVQhZ4Dc+tZ6EJt-Kh=7!=zlU4Z6*%cEH!5$6Uq2uq7v@|8*Ah zzZ;@sFW_w!!iDWAlIvc9q^^4&h70GR;-bL;7GWd1nshv3E>q_SrAB{!>e@?JSL4Z% z3h2gHv8<#-`l*o0IeW+4Jp}fw^AegX$y_IvumM9%*Rtxi5{l=n#%)H^k*!l zLoY+cJ9UJrb~l;U!V@`ENhv0E(H{mmXQ#2OhgL(1H~$8FdNCR&XFfWZA1}jvPIkJP z(s09v_1`0Ud9t+)43D$W@L~O@!tqm$OfJ-1rA7G}%o#m9kciC#GpVy97W7hnpQYQ5 zH?pONPcA@)?H$#kB#}U}! z!}?E?O3${M>$@jE=<*egUqucwd;U{jvsq^Yn#jT96MFWQEtWc@+%UrU&1)V zI?r%ZZ1{S9{C#FNR5nel`Db5)HH~=dJqJW^JZDq8_Qa{xMr@y+?+;Mdw-Lb!@r3~&o1~*p$;5+tX{}9zE)BEsDL0l>hi-4K{cn+{2E!_z5;b`DMBW^f`~^tm79y6ykJa) z!>v3UM9tdxEX0L{g^f6Jks}bkqHJH_)y{wCrpo9Xj<4({9+nBQF%&*amBkbQaw8zZSKTCaMumGvcoNl z#W9z>+NtJxy(y)Jx$ND_GMsKQ!`J2J?ge21$wb~FpO>~u41k!6Q=Z8qC2lR_TP~#u zCPi<)Gb&LAH}5Q>RB!^cQ!f_CM&$kYjV3#0cpx~^L6CVf+&SHf({qFGF zk`0vornIr4*~K^F|pw zuEJF*BIII+3wpRd1p9Dl@JwR9qrJG|WZt4?=Ini3Qg_*Eyi{LssBx*~ViKxoRvOqm zLwH09QsB>`x#RTmZi1jvVz)PWO4l~wjaWu8t~^-vJwWD@cmZpeIbp1W)UMWc7ZSD%LkSe#O%To7>OY`GS^4CS zaG~lNsFGZF=5X~<04Pe0Nq6aLe0en|&U7~$PJ^eE`H*1Ad9rnruIQ?&KW&LR=>NQy zibdR6X;Y(Tjpw*>?`1J1QQi7kBaGH9E-#-}WfPbn^Xs0D-e{a(N&%yIgf`}wG1 zxqBx$*#d>IsthZpq_l&2RU>Iq=ZQjY?W}Q{cmY(xNrz&gSDei5#TFnf%se?N>pJ^6 zOl{9)SzFl*2~fcD(m^VTBthBRmco>cME?i&0i%F}@mojtEC`pfj9yPsw%+ zFmE)naEfH2El%SW$F-T~%vxQ_h#PE;V5DHbXWC-mWY(daLG(+?)s!_c;3v(xC$E}w zeG$#vXU_rYKBZL5dSOYtKyv$$Gu3;LqVRcty$i*={#Ggw2~Bw-`vQ zn9E3CPqdgiTW?;wZ7x$(uTZhCF1TIZwJr*#P$%k_DqDTkW+sD@lf86)AV<18%_X?M zClsJ&55va^Ms)kfbuvP0YMxmlm|sCRmF5#Jo4-?3nizry20P+JHQkKnCr;K(s>?S3LNIAz37G!W^?*9Izp+C zySXMgtwUZX;IZr6jL@uM@3z{Uqe`(jGG(jTK_6paX1~$ZsGRxYHtLGjV|ga&Ibs?0 zCXG4lCjOL{Q)lp0rL!Y0rO`m$tZy`mhF7X!M&3M;n}MMh&JrLH4DE$Y{I-(gy7?nt zj%+T5F9YJ z$G1tz^2;ACQq~2x5pz;rH_&4-4HcNeKtvcIlc%UP3hUt<@dhAY-=LcAQlWTo`-(IF zDH_a=CR#7KUx2}N8bx6XTTQ-lMW5)P3>qPQi7iOK01;Cxma7%UjxS$4s}ba4056q` zF>cqF^s2+@OOBf}%7h}ums%Y2COD^|z^*;p1cDbur}e8loWUj<;+Xip(O{^+X$da4 z=g7sY)#n~RZow~*kS@F(b6JbT59|T5lJz)& zP}D(lw-azIFNufjW))Vwp^hKp^zB89U%|CgTO|*iYC{`oQz0fSK_rF&_&{28+S$Ts)U0H)Z{!2;9an4}Dj0@SQ#mb`Cw z?E$AdwAPC{>8F)Igf5qchcTBX&<{Tig~%y{J%{U+buAKuUS}>hEBPsmVmQr}t#WjO zjB>6AR2TI2&X$XC!;vhXTB_TeV<&#rWDh$943QQdXN=SoO*vhtn`lEo9W*doqx91~ z3h=u~uE+!~&esxU0F%et_QL9TBVo#7e7o+*nx9g3meeo$*}K{-`ri%T+{*CAG;2`y4|**7LY9Jwm;AOa z;#IS2-EAdUdy@3KBsodTdoPhLk>5=~rAIkgT;V|4ZHF1|!Ik6S&tX*rqMbbAvFwy& zH^UkQ;|6UpdRGRE5S@;@e71t$!1%@d_xeSMNKF3rlZW4MX>OYxQAhCbE(uYw^Em#d zI($?*o#THQD{#W%0pR0;u2`k_=Hu}St>`z8;@*nzjK zm<4f&L|mKXv%y?XJ%ArtvXn}A686`7=cklU3T%+8tcVj?fNab=je)gxRELAwZQh{M z%c!wqfurs~R8|wGCG~?n#}{P&6YESVf2cZW>U}4@z>WN_8eYsf)Yb zzEenQtao{ex&amz+kj|ucVzCL9>iw8kzKh~=lFoKk8(n?A1)RkB>>H0AIc6YsP|&y z3Nvr^*^IM}Vg_)Xk=C_(-odQT2^zT6{u&Vy zguDWyBr>XvD_ve!<@kUTMPrZY-ipmF5(O2p;B2!hj^vl-pfd4u_(EeF#w%W_UdXTS z4_i?*fbAvXxx&F;4h7I;kIxwDcxh6k!LuPF`MLlt zKWQvYHxJNB2N9;r$DqnOcIoYE@mm;l*`+J$G%Mhtkn9lrtS;Tc@-(S5j6>Sv1Jju@ zjpdB;5IY{`Fo|*eP`&dn7KokzY^rP2EHNv|#y@|l6i*h>79jMThiD039rAaVU9s4X zjpulflNBswzVGHH38Nf{Iu@(5TH0n5*?wDqPX-VJ_PUaBDYQ{!cdjDm z%Qyl{SFHUAOK{W9YT7aW4LXhqJA-|l#+SL3K~JNSKvy#EdLYox=)<^2Tc}TX`uR1Y zD`xxzh$0@qt(`~MgdR3OY`%JpoL2d=zBIz^T?sAZgnnyr*u&&a! zZZN1o#oZbW`z44B_}o@0!E#OUci3@awS;dRW5$x!YChEMWwC~N@n=kSxFwl^BP31yig2Q-D zIVdEkvhZPD?BL7@^sv+tb6MuhE=c)tnafdw&u%#0f(-=Jxq@qXgX93yeDg&wO#71` zPe(a(c5_B9T*-ANtA^?17l}D{Pu^6nbH^BUg@`Vw8^O$M?>MWRBHIe4J+A|PcR*(W zoZe?1g%Q(k7pjBY+Sutr&mbV-Lku*#RliGQTnMbN6tjXfX_sFt&}haUT7Y^lSb%4% znYFgLNI+JlP)2n$AhDQNKuE+|jndVe&fF~)4kbXYL6;0{-uE#BzFCE`(qvuIU@v|$ zw3IunS}4mbhKeaMXD)`^+U7Pz-LJ$?#|JGhL!FD7;e+b-sL!k_R4x0h{4SZgRw`x> zcHJ$XxZPFdPSe^Y3pQ2gbF*S9bNvt~5d%T)|OZ7}wE(jBbeWE|SlF4%J z0m{{i@hM;dtY;LC=;Df2u}OEZljw`{wk`=`7eU*>e{IVVg;sS1F^8^k4cK!(<-0S~ z%x7Pwbkys2!fUUq?9~|rL7W^ub3^r8DBLQXzt#eKnUG#q^j>#-beGGo@)jNMNpVs{ zM9R#kT~u_rpC=v6c@psJ;WMNeWo>X|-m=gQDS(RZG;@2zNosuDkfc~RKZc7OSo4N5 z*r+YYM1oz4wcmsoK=b0PA7n<#1HmGZNbiqx9Kv`p-hy^^3DY&>mRt$Z;znMjCru0m zGv+4q)VrX$qDjjWH9Hg>-L+U0CEfLyo6sN!7)jzfM=GpQO+6y5XT+s%>9B@w8=z3$ zDvSn$yO3R=fr1$}VfWAnEDqBpt0XJ(S7!*|q25oH=u|7PN+s6YbEKNvpx_SIYgDgk zRy?P6tN`rYk7HjqsRBfv`T=Mv&!h?^;hXtcFYw0rp5ROJVrrMMqCU(j@NcnX_ortC zLuM0Psj!RDim@<_5$SR^6}$Ck+>pYZ(Dz(zjwAAB>^Nk0m}2D6cU`mZ?J#cPLjK7| z?3Ux@pCdK~Oog_4)Ujm3R-5DG?xHP<`@>TFoV+dXn8Hz3RzM~=VEY8v zw3R&@)$w;~dw_9J(f~F(6bvX?g4!d{3v=rO+n56z8|+(g3q%g)!3O7TZ3%4H%BmTv z^iZ5O1#-i^4FlH&Hs0THbMqH292NN21`?f$5i{)*4rEl2V7@&a`?tlxs%d215 zcGV?oso)Q5*sN#CviCt28uYR#`N58I=MO-cv1{8Z4OIDF0FrWdH;9`O^?jU;Sx@NB z<9_5X_rjBI{e+D2T^a7h?C{q3PUwA#%~En_AN+d6qd|!E)LNU)At}tEO=^_I%jrB9 zsjoHL$XGcVGvVPLt_>k-jU<-ceU16Oxj<{kD~ooXbVfRn?)=<^bH%pyA=?zTz0b(Y zkNpphbJ*q5X@Suxm_uBE+3YyZ!H7N{NVQQ5rP_6vnU0l*?Ueld2GIfq2)oLua^5oG zFw&2ckG%*bC_RMn>J)o^5WM7QzbOZDnZuLotw;3|U?OJt4-4A+@(b-jC z*GSikCQS+^Ilp@=ds_|tlEvUsr>?Rz=FL1WK`eCEGK z64*i6R_^WOmiv9&d}qk*$;fu_x4o0+?VC(Kh9P*-$8B#j6oGH90*#D$3Flof#6^IUFm7 zWI~>aGt=?Dt5yBh51>?IlneU_9w|4Idj5Piay3t;qZ>SA6*H~D!}i#QS&XqU5w_raHrc_QeYXlJSyX%+I!?1u5Q?DDgqL zKWnY4c$D42citsWW|eDf0Jc(9N$M^DsCyjr;UnydF}G%9lHnA5&OX5fN^)~1EK)~K z?bB3FN1&X$0xb${RIGKPnh=hw!qV9=%OfHglq`PvvipFD@S0d@Uiaq-9O_^jjJx#} zK!H*AuI(@4YA}nM#$tY{odQJaBw_#*43Jv`n&{Hb-Zevg4eS~uy#y`-Lr)i=&=P#P zJ$Ardv7v<61D6q&S`I_vK{d?nO%FtU62hty#n6N>1I9rUZfB{JvtF%}K@GV1w3TsG zc5Ot|2`J^V7M5R>&lOUW%N^A=)h5;K`WL%gEzpNWp!_==U8zMc;6NTT zd2$K_lNpnqL*^h?p5j36P7VjrnjCqFZb8H{%`fVrDhKTv*?ClYVoLlRwu_uNn_E}> zj?fDS?uwZcuN)$z#59RcQaN5Zd0qfz?vMCW(R_U>d^Z0DsGW)KwHo2{6awigOp+E8 zk5$@555mnMzI|0BrSZnbqR%lo5vwRF?rtoamd|tZUlBwDh-H$w(NKNow3%(Om0d32 zl{2H5G$TyqS-8Dz9Uhj$wR@RktS}&nOE=6ej?Se=id%}nxwl$(1zwN5(Pl)r_r!J2V zVL#*8V5x46+K9^+SD5d(4lh-17E5OW;aQ=Z@n>hcv#UeJ4NO`iGy>wc;qTF@CU%~; zPz=#zUHka}-)Scfc0m`@I{ye+iJlAln>kMwqB2*)IffQP%5*h^7VE?!)=0eCu3;?? zN~Kld&?vWqn10BUQ|E@tLA0W;3{IKRN5;vuVwJ3aSaBuSA5F-sMF+2)U<}^POBv90 z>+XGjvl07*iEoFC8$kEQ8j zdv6NUB5VJXjM*(QH+hF)Uj*T**DyzCi(#R|VwQAASOo58M$N8e9q+2`|LhvtnzNC`=YFCVa`2Vg_7?L z(rH?VM&2b+%ylhW>th*a2`{Xns`$S4lx22sDU^6P6}X$zjn%(CX?i0V!2_(Ld;n+a` z;%5qT)V~z((L8053MT#YB!8^4RWD4^-d{Ir4B+BuQPu() z!5Ba^g-za;Rue%q-*+=1y-M=fNZ4Rwg&;7`0VUIyo15&b#|Jk%Bf&!PWX|-0W3oqUD1V;UB^zjVOL|k;Zd0o#ML;6KO#9`MFQlgz9a3z0{D18aD_ZcIAK-IlZ;MeHPQAumdWOo7J*V%vP}D zp9Wx$F;<&O$!h@40l!ih&L~Wj4^%puJ%lgE2HwLVlVS!-RdO!MIWSHN1GOcF^Q4hk z#@B5t)`;8+QLh3imd&TWz)$B;amooZD>>I9@=0?9QDdxfdg|AJ=q5L3*t#A>`JqOv zpulcA2<-@fR3>~bn_I!6@$G^yh$Y*_ZsIbwf5jpl@7~WhZC|L*ACw*E_LR&51}fDC zCR_s!>ClUZ+udYL$JyUJOr1rgUA+Nn7lTZ3LjSyuZKqbwL*G&vWU$KFi^b)OXKzKG zLMs4j)6`KAWAmPiCzmd8)7r>|7p^?z z51p{W*&M9C$U#8Yp)4!^$387MUI5I!rCHy)8GFb`QOUXRk@DlZX<0_HB5q(QpMQm8 zETLMq^zoB{r=IoT^VoFgz@ZioJvftJ&h)jp9&ii>#PL?h10&L^=XOzN@#NYP^u}b% zIIDDlj@amxqQ=qlar1k;X((k&*?6~`xK))l%vR`;;1 z5_ixTqjOX#k+_H}Dn;iE<)2Pj2O3wOGh-C_y9I7z6J2dFo%Fm0(7X!J<(<%eqMdEY zD^$#tiZMdk_ljQhYW%#a zyYB|*wZ^8CN&7f)e|@-w>g&L8--YwsqMvAN-b`NH*2kIgHrNqGz)9hRI|$fYA$`wT zFtdPL4iIuQ=|^y`&-%E)HhaP*mf>ZUUAv9 zsLXgu@vv6xV?s0BLC5Gr;!!8{MwW_ttCBQi)?QaW#fLE!x3#67>Wi<17qQgChxJ%Dcci_8HjK$7tIBGAQlN=;1=~e84dd-J zziy7@Y!)7Gm(6&Bpn%=^9TOj6c|*c&!)k+ zX7oJAZPz7V=}*jt+0fan9klkLs-hF>_kGS&Jjo*Ie6+ybRc6Elq7RzL1OROG$WG7G zAUey(cIzQ_YJn+w_J$U{mYi!u)7Z861$jwumY~*)yW}5)g~@|WI?}^?j=TGFiIOi$ z88=IgNrhTh*_eSO&Wp(upkNTEJKt%nY%#81JNIE$uh9U7ja#a8XEmWB@u$JO9s3e0 z_cqZ*?{u=K)xvvFTqe>ZM&5B}s6gw%0)1asT8iaQ#UbVLAKoL)puuMW4V`9o1_f&{5R~4n}}kH;o7r&8Zv8= z^~;Iio=FJdip!ZAhA5aeXYy|4fwmJay&4knBU5!epPiqw!lsS@3|IIW1DwM{e7Y^i zLw*ddU8~zsaoscoLK425+}c@fx=a`?24dkV%4kg&;N&;npOqfTJVrUDSLbpkTLV)k z(SxjT8xNJ8%WNo<0)>;5fQ!>=;g@CuTyHfnf67CBPJcFSTK zfIM~e8D=TRvU~10RxynzA`bEf_&g|zh!0k3 zMn8JTS62p*{HWXA1;UZL-Vt4{)Q;n1v)T_iUWconjC_= z7fCiSeoMxc0O(7*L-@!?tX42gES`>@?Pjy%4?c)jP`-;fZr!-tlu0cvKgSU(PR*?= z7_B3b9_z_o88!>T+_wDU@=E^_<`#CRG4@Ro@+!49OfR(qlt{Uu7I*2`m4S?c|ES8D zWS(O90r;o8I?g?Hf)rqG4A*CM-9bq@z%jbXF~i;*%1*mim0BL5 z=8B2pE3u}%TkY&>4@Xcf{C5aCNTFGsf@B8f3@TU>am_v63(!~Hbx9*M^Zc;5sc!Pl zP9NrHfCkZlMzPOC6oHWN&ePA`TxvyVd z0N^uuGefV3Ih@NRyEsY&iT6AKlBM`R>0@tyTy$3!9WV7|$)$Ca61h^~uxi7O4i$bl zUq)3#bCp-VS3CfA`OYm%V`4+3)4A2Df9|G6;y4DT?emccgh$B<3B;$m)Q%%ny0?VE z>4IbJ?DthNG;kK4VZQr%PCxvA&Jjm!A--_p6xGK&xF{C+IF9!{ad;)>D{S2LR6f)1 zlbgXGr#qwyxKh#eHH9y1<$B@Jnc`sR>e8tT6qgu+Zq=-K&1Oxy%McbW$U7phseN7% zB$~Lme7vZrmkb&{i;jkhkPPmx1BkG8i_;O>&BbdbP&-;4=dh~aqK)3$;OF-<=v&c4jxECl=5BXhq^ldycP# zU6vYe2vN|!B#}uFMQnU7k9$cEcDZd1d`8U|434FC>i`oU^%o`>P=Q3jvjrf(K4RaA zBoE8Vy8r;>g5tyXaDl_;uY9DK8gu5Cm80G{oPAxsX&!J}R%-2qutjvLf^X2W(F(EH zoEg$brf@5^cKVatrH4rM!NlEP_=llO^Re_=2S=ps-dx;00*T{Nj~$bxr!kA@6)|P{ zoUEct%0tLi3hn_K!5v_cRvt22{z1PJDwT^ZZ%SE-V{gvmkfTM%aA=4N9NokvQWUD`#9r`4EW7q{!8CaMSC z_Sx%sRu+cHsB7e$j|BECZs-Y{)#4{J>k}%OVURmHhW3foa1~cITa>P9Po7rjAbnhg z%xQj09?CXy#^>mI&H{zx!~$jS^+WHTul(1%{hSlrGDFW zpo^x+=8$K4!_J)!lhGBTz}{!C_&az+$!PKND)M^h5^90e9hs!Vd7l;noV)X+KtTI+ zf?pNlVrq9qtqc$7Fj;(Z*N`5>uQCU07Ei98b0f1BKQBEwtYb2yWZzt5!EVaES3Hq| z;MbeA{m38<_i+2!d(!2bP<@MFNmHgnFRs}i*Dt%{hhz&U&FN*d+TdBOwhH>Z{f2K`io>i^2`6x2sw6sa$rdHcxZT-Lv@u-;PDw$yJok{z zUG5Dn&vG{}2?BQP(yk-1pX5n$Y|`J9EfAxL4Ita)BIUs6p;mi+u>$>VWQ$efWu3*` zl7qkE|2njR{Fhbdv+r*4_=4ovtlNBC4LTuuwG-Uk*QK@f1{Ka!V@^(3@IhAdA$Z@V zz?-{M=itf6+-b&j;kDl23MwgvPh^hs5=M2{2L#NR#sn%kiIM2@KJS`+E;IuHR0*j3 z9a|yqxYs2m`DYsR=-c+;CXbi`XfMJYQsDr;OW_51`tYc~4jtKt1&rNzxG@`i-tJSA z`37)Wyq6-sys=HnVP6g%3e2RPjp>gTf+1xwMMz>hQ(zuQ&9#($4b9nya|_g;;1*su z8r|f%$tdHA_MT3Z#K>Kq7dG0U*)oitT^AR8x$@9)k7X0O|J5d}AaJ05;f)z}9l8o67z_z^hC@tgzxI}I zgIsPme5!#sgrj3#AHY=LJc#@*n4KEkVYdyzu(l#y>DbNqEYV)q?pE3dPcY454&Cx6 z5#!-+o*1tpeQ}LXXocJS81c(fpp!1S6sMvO(+u;y?0n%6S-!s*(QYHO$@+4VaNC{o zkxJD6l5HR)Sw-aQs$@Qq{4CHkz6{l3p3KTZ*4_6 zAulcy?r_<8UHAVo<(Xn#eGVmwAHPhh?9m=du=v>&)4&zsQ&nsI3x^f%V~gq=-0j3A zINZW!j!3U)sY3?UgB3MUIK5v5=jBJ zot=B(Wg;F$86WxKAdG8+x>>Y&y4o;-eQn+&VBM};Wl!^p!VDRmst2{rU+88*R*L#S zm1%1u-A-3}z!K2(_!3m?F;V#Pb7oD5Ef1L6WR$c(#geK=2?Pm`Q!HallFpT?bB8g6KnjdO*6sCdK8LWd!!!AbAT_?hfs6q= znV;46a6*_WnIz;Kd}!sid#AW%fSC{v0Lxj!5yhbk98rI_lI0P7XxBV*Z15q^fqTTcOEnhW-l-1& z3-dAg<{1HBkM&9>@9v~Z?!!ISsCRJq-=@VekG(cZp|X2zS%>)a@_g%mm>)0qIi$YR zEb)%?Ryticm>iu+bfUct+qPPf7`R^zv@z;()LmuhyzkZU`AcWdId2~>gr4QbZhIo; zy8eNSr(d-gfK;7)+z^P~2`8>w*IueRS&&aFz9QJEl-k7zy!WLHOu zk>R%|M7WYd#tO+=F^%S&3?N3kO}bgJld$Q7lJ+?l>CvBEi{!o=XrXMKv;ecp&XMNd zf-m#=7Th9GAA+0Y+6Esqw%b&l{4;6A7LVpz%$|1m3iGtSTHm7`gD1uF7|IHL`b%kz z!6;gCuZwi4hACqC0jl00ygIT*OL{FP=hdPGjbn>A4p9^fWYW6$GI<#>}~XMVaz;Hb_y&C>w4C<4Ha3eQz;F0E%gB@&z}Ap}Iah)@($ z*utt>8=%XX7Oy7y^#Q%s5%`9x?yN8<*cYNr<=k01ND@QYfqvSKAXv|yceuTTq!QAtn{Vena z!3vA40Q9jr3t=hqV_}XUz0QhJhT+sUo9gzi=Y7{j7k&)%xOqC4$>;b6Q3$jxC8(0Q z5w5ZPJ!dO7LBrc5{?38@?1$-9u=G8gnat6`XTKUm+fVaX6Wui^VQB%Gf(oDJs89y7 zd02K`a)gUj!DuoHxsj$f`bzWeqLpb8o($Y*WD40uNQclTy#d9}@MU%@Wi{N_hYMA= z{Psy+CIJ6%aOl%PIGUmv@RndDS}(WOlB?)~t(-y8JH8}5*;{+i<8f6SoeB zznx>{yTO2F>v}`0*^k|-4|o^A?CYC}=(^i_)mf2X%z$^%L3D+S4tb!jJGH@#6_im}vUEVFZFT7G}Fc3r>FzhxI<~wGK$d|1f8*LVQ$kywd z9&*wZbL)~roMm12D9w1wyNZ1Bk-$$4bZQ(dPBTUY=At+bxxt$=cj{TI*^ictEHM`W zRi?aX!?l`s0Y1#?M@}c!ugtssBpmm8GmDPi^!;9VnRQrH#Uc!q6S^mNM!5Z>SEEr2 zZ|mzMRnVxVi?L^R&BIqBLVz*{FO}PYO39f^mo6Z)hI{=8_Tr00QUkj-1#f1>=KAwC z6s20V4Tlkj=4DEQ>l`PJj|s>G&TT#TW62^SI)*mh=e||==J0GEM&;KKFhdfotYd*m ziy((pOjLXUUTvw~e3zx{Ca4Pa<~A>eo!%tFkJqLrAyJyR+a?`*=yN)) zsTLTOKz1vvDWAjVAln!NIK8U(DFn0&rC z5&tD+tMG`=Qg)UcBP#2L9mNA=mnWe2%Ww=YKDM@c-g++gE9Ly~iRC;EiZd%YlOTip zq*MZ~-*~vXs2CJtfN<#O^2w!3ONdlq0c}Q^pPd$0a8bQE$wSQvf>uDP7ilDjn_9?C zQ4l9fAf93Y98(yUNn^oHeFDf5|M}}N>Y`{|K2kx&i%p8=aKZtV-YV7Q*)^6ka(1myk)c#~fCx>QXig4) z+MZoQd>~F7r=^}w?lB5VmeT$tSui|1cDaH6Hm*~`aX}}XL4{exhZQRX$f`GiU6IeF?wI37G4JQ6%NcwX>=;Nyai4?ZDS3Qh#e!O7rM za5{K2I1{V{j|DFb&IRX#)!;(#cyKYe6kHCT2%Zd{3SJbvIQYciCBY{JFAc5))u0w+ z!PQ_r*a%)0Tnie(X3z{;!OMeo&!CQhK3w|Pa zYw(l7PX%uaemeM>;AexM3*H{QBl!8?*Mr{(ek*uq@UGyugWn0>9sFMK`@tUse-!+2 z@F&5a27ea(dGI&E-v)md{C)5b!9NA>3H~|wm*Bm@zXtynyf66o;QhgW1pgWQSMY)0 zgTaS_{|-JJd?fg27=&RMg>jgKX;=ye!ohGT91cgq(Xbqjh2!C5I2BHZGvRDF7w!r7 zg$Kfe;i2$wcvpBdJQgm5cZc_cPYdr2?+c$E-XA_Ad?0*gxEMYdJ`^4gpA|kkd`|e> z@Ok0$!;cAH5PodrerEVt;j6+|hp!1=8-7msy6|(u&kMgG{KD{y!Y>WKEd0vwtHQ4hzdrni z@EgN#3cor0mhkoAw}#&yz9IaM@H@jdhTj!_clf>G_k}+Y{$Ti~@Xg^5hd&a&CH&Fw z$HE^Ee!e0)5CH&R!*TP>9eSk=;7#*=sD5zqUT31h(0#@_~;X& z6VY;XDmopViB_V=q8CQzqVv&ebRl{?x)`lRm!iwj6VX%Ai=vlApA>y^^wQ{4qDpin zsz$Xai`Ju!s2;s6x)wE}&8Qi*qOIuVQ9J5H-Do?y9^Hs;Mmy1`MxPeFGWzuBGosIo zJ}Y`v^y=s}(Pu}mjXo!OUG%xp=S80%eL?hv(HBKu9DPajWzknhUlV<8^mWlUM&A^D zbM!6I>!WXtzAgIp=nc_#MBf>`G5W6PyQA-kzAyUz=m(-7jD9G3Q}pKOhoc{f-V(hv z`pM|0qPImq9sO+dbJ5$QcSJuQ{X+DM(Jw{69Q{i4tI@ATzaITY^qbLdMemH>75z^1 z?&uGqKaBn;`jhBSqd$xOJo=01FQdPT{yO@b=pUkgjQ%NlPxLR*d!v7i{w;c6^zYI8 zqyLEhGy1RS1JMVg4@LhSeK`6^^wBto!#IlLIEmAEFdmAB<$8#-9>b;wy1A zUXM58di=8ZTHJ`6@yp|O+>NitH{+f774a+M&xk)W{;c>_@vGz4#Gf6%Hhx|Fx$zgo zUl@OJ{3Y?1$6pbDW&G9g*T!ELe?$C@@i)ic62CtFw)hS4cgAmwzbpQp_HR#Zom`Nrg%l5bAFC3$`Ft;x3~-=4f7`Hti}lQ$;coqSL7eaZJHKal)j@m4_yOQ5d zekXZ%^1I3JCBL8iVe&`GA18m3{8jST$=@V@oBUn!56M3!|CGEZ`RC+clJ_S6n*3Yx zzU1GN_b306{8#dU5=qkdMsT??@6DQ-kaW+-k&}reK0+qK0AF*`rPz+>GRVU zq#v7pT>1&=QhFjiot{Zo(#O&lrf1W0>G|{%)0d>xw3cS+dit`ok+#!rx}9E6Z>FD` zep>p<^wZPNNIx@uRr>1mHR)%kuT4KEeO>yw>F1@NpMF95Md=r(Uy^=l`eo^tr(cnN zW%^a=SEpZ-er@`7>DQ;BT@zA^o-^t;pVNxwJ!zV!RkA54EJeN+18 z^eyR+rvE4XvGm8&x28XtzAgQk^k>tzr|(FACH>X(*VErfe=~h&`mXf1)89$oo&Ik6 zN9iA@f0F)b`e*51q<@qCZTffV->3hO{$u){^q5h3(69yiZaR;1%Y%@C~axl zq6{(3YG|5-jMA!rGMuQOfPf$}#fh>6MA-r&L-wN#nKA@NN7AH8e(%rqz3+2Q((*jd z@Adlq@%snuIVbn{j%$3b&-MBG2lxm2pY#v%5B5LhAL>{8GyIwUEPu8?&!6uv@E7?t z{!)LLf2@C;f4u)$|3rVeU+35R4Su8F0K{-yp8 z{mcC;{44#d{Hy(I{A>N|{Ga$g^?&C7!vCdzz5gr!*ZvLujs8vk&HgR^Z~WW*+x_49 zzxVI-@AmKU@AdEV@Av=UKj1&;Kji<>f7t(%|A_yn|Cs-{|Ahaf|CIl<|BU~v|D69{ z{$KpR`p^3>_%Hf@^I!H~@n7{{^I!M>?!W23<-hH}w=#IKMj5s{5<$Y@XO%(;8(#7!A-%zg4=`N z26qI%3+@c=3hoK+4ekr>5B?B55Ih(>6#OxGBzQD>*T<~AP zUxL2|&j&9AF9t6Ke+ym?UI|_eUJG6i-U$94ycxU|ydAs~{3CcbcrW;8@bBP1!Mb35 zup#IPHU)h_f3P_i2nI<&E5ck@8Ro-6=!an#g>g749374g$A#m=3E{+WQaCxB5^fW2 z8%_23_lo73qKToIQ&TX(ePv8ZsG3X9^szh^l-0m?{J@R-*CTh|L}nD6X8MO z!Qr9dVd0E$W;iRH9nKBsg-3+*!v*2O@aS-HSQ9P@mxjy2W5Q2|p9zl*j|-0vPY6F7 zo)~^EtPShJ`miBv44c9gVRN`P{CxO@@YL|M@bvIY;g`cR!ZX9O!n4D#gkKH69)2VI zW_V8ct?=97cfxbS^TO|j=ZBYsmxezKFAuK^e;WQQ{CW7x@cQsq;jhCR!<)jJ!&}1N zgtvybg|~-yhIfT`hxdl}g?|Vi2p#Uk+ahUkzUiUk~31{~o>>z7@V5z7zf|9xh<1*4iKay#ias3e8htFWDg{uBba&9i0-biPlD+kG>FnF*-FmEjm5=Qgmi?cJ!6# ztI^k@uSegAz8RepeJlEQ^quJ3=zG!m(FM_k(M8e4(IwFjqD!O8qRXQnMOQ>uMps2w zN7qExMn8_Oi+&pYJi0#mRrKrVhUmuVrs(GAH_@%pZPD$~Z=*Y+-$lQV?u_n=?vCz> z?v3t??vMTuJrF$@Jrw;hdN}%1^hoq*^jP$G^ylb_=*j4*=;`R0=-KGG=r7Sqc@_zM{h=NMQ=y%ME{81joyp?8Lf-fM;oGz(Lgj94S{M^#)a6AgE)%g zIEhEcW8$&#xOjX#A)XjdiYLcY;%(#Y;~nCi;t#|-$J62u#UF`xjXxUi9`6zF8BdS* ziuaE9iT927i}#NYh!2bpiD$)g;<@qR@x1tm_{eyEydYi}FN%+j7soa6l6YBsTzq_d zLj2kI#CUmJ7uUxPabw&ZpA@f*TjEu5YupyM#~pEJ+#RouPl?yYUyM(UPm8}CpAnxG zpB;ZC{#yKv_`>-6@s;sa@zwFQ@sH!{;-AF7jIWPxh;NKi*JvA8{ZNC zKE5-)JH97=Abv1@D1J14JpOb1MEqp@RQz=OO#E#8T>RJgh4{tzrTFFemH5^8wfOb; zjri~JoAF!m+wnW`zvBPI>*I}aZ`>ab#Dj^KB(Nn-pM}6zR7;c{>cH!$CCq-Pb8mA4oVJA zK9wAj9GV=KR3|f%naQkVPBJ$+JeijqksO)KPmW3!Bny*8$XQ1TA!$sSk`+mFa#FG~X-QTktw~$bo^&Q%Nq4e3 zIVD+>tW7?jd?EQ_a%yr~a(eQmPV%kf+sSv5 zbCdIu?uvVCEY3@;@Oj^<}tAYl^y*5SKFyV;PRFTwFv}t}tBXx-vxN#uQ8WJs8TL{x8sx zo)i-q{C|ju91I#V10>||{}BiIY;Gh5a#9)ok)a=_48uPDcgV-ZWw^(c!!VAUKsZY1 z#(g8OjgiPk3DVelh<46TIU8611P=|>i4m*N2>@osrct4!MVGN56I}m2jRE8FG55oyEgh2Q}IWll1 zIKcHF0KXycSJr=zh?RT+y6}#Kd{vdet7;qJbN$Y?#kS=yuFmQSEt!} zd9HqvW$C5-T-kYfZl2}k=l@@1jy&`pa!_TQPmx`|NKW~8%O~F>i`+VA&a)2!}fYV1r|BCr97#8ol$X;>%twi#75y3x@#_f*| zi`iYgzO`t5>#_RqIDLE?k-J!2arm4qV(u*7{%kSQ-ZIW!O?+L7tiMkroyF0&q!IL; zM9A+KANN{BJTe}hR2B*EO6=>RUd6mF;ysL5cUD=1yNKvkvF$O$wZ~aZt9UkxW?dvZ zGJ-vo$W?Lc*+i`0uxRx=#YlB)aq4v=;?b=~qK^@S{_i5tE#prYeJb+YTC8c2X2r`8 zI8r5}>H7=~ZTzmJPSG4~TW!n&C|q_1XN3-UMTEWW-M6G;;a%XM3Zn+nq2V#r)}e4Gr~QVH^RSyON#zu8%iQ;FsCS zakcGspCIfdPY=ni4<(nL?@e~Srd+73&oq73BjeM&G1&!-xoKa7B=6Ov;fvFRyUE*r z3AJ#Vm{pLLdiu1Pwe33Fo07T)q<=nCq*|11JEy@D>1tS`Ga>ZF;MZvuhQBavX7_Sw zPeFflfAAg;-p#?r?mTe2Yk?xvrzk+p%+2v8Ro98i)4aU71x|`n_0bFWeGN83*`YeR zNAIQHM~d8o`r^oEorooI&*^(>g8Z+BPrMK{H82!X2A><_pg-Klo9MU&!!OIjMEQ3? zO@HA3G1vf>a69P1Luj1Q=qAyP>B?_%)Ig8qUUGmV3?9hDL6}+1@EGSz z9}a!V8w>w$#WXq}SHYcKZ7;QXM{m1qj>WtkMt+{Yk8VQh*=D@($fQp!eQ% zKH|}6nxwb2;R7@EwncV8)Lf??WmLB%?#c8MNc0eq3@5iY)CK ztHGtPAWt#bUnHJ0`iz?->S&WnPn~U$l0x=i z-WpDTXy~G8JezBVWZ+sSjKW*n)A(W^Q0uq@9PBE|L?Pv)ck5rtF^?sY3w^ZVkE{qg zC7Lxc(kSv5%e?KYJ4u^5+d-<`qL-vEM=*zir0KWW^It5|Ut(oQqp=}Ow0$Ru2kRcttZJKyt z*;?DYAB|41*2LJhi{xRrv{jBOJfkyI(_?2Ev^D9e(-ii8jNMdMhiUC9XPI<=N=mFZX8z~i5v?;eYHyz2mrOI7pL}vHaV5RqYQ&VB9E!0izo-uWp z$y60oIe3}sz#wSzuceG&T(X7Bp){@LPG--&zf_F#w!zxSIWFc51bHVIO4&?q=GYz0 ziPW?7#C;$4MyGRO8glm8(J;TQKR`Q5^WEL4&wH9Ny+*lCyYXzO&P2w~J`{--niG%0 zlcgM7{bKzeym3g34LA2#g_9*^Q_j(pjiq)vnLbM=Ob4gb&e%xZe$VUPBwPB5HnuR$ zFj;ND6?gd5-o8gw?N`*vo`C}g*NoH3N~h8cAvY^PS3OkW;LT zNCQ3iCVl;G6Q-SJ9P6XUeuqoRJV^p}T50kJ4)t~{d4%^37{;=H+gj*uN&OAZpl=VR zRQ7V(99C>b@K4R>w=hZA*se17Qwas_^N`23)kI{TRVTU6lEfE15n8qfl&`vyM|7-N zH_9N?pOcz>oepLt{#m8fY+n_O?6uB_T~+k0ihP)^vCW5gReDU`T%jtr+Ps_EvsNKE zQf8zz>~LoKz0sMylEHREP8I3x=ny(ljls)Sw6j_)fVcs=r9~4KXXK6x_C#1s5>--X zKms~_xdXlJ-0)Sma;l;pO?w@3wY-tuzRMyl1r%rz+pPV?+ZpkJ7NR#9xuRdTKOPp4 zUzfj;U5vUX*P3RriY>ohmI&gqCKFoIUhBf_UDBfk(s&Rv8qVnM>LLi&w9;5x3RGOw zWv>Othd`VbujW=4=%p*sNF5{tblNIr&91~y<_qg6(Vys_OkcCz%U1Q*!T>3=HrA3k zcGvBene_ENG!@{)+z8?K?A9vFBMD))i-9+ie%Y+yn?E7f+S*Xtk*!Z|6~GlZ5GFu9 z)&3R!7t4BxJH-Xn_^x{dD{}PwRGQyLyiqPuNlHpV)rY;`CBZYH`ue zd3&UGIrBwxn%6Yc&qzBIx`r0z2XrUZb#Ty!jt#)6H)}Fr@+^l8_9R=WG!k!OizNGxJuV!b@ z;BLu16NsK0nvnCd(40@kOTuyWIZM6CGwzx%}ib z%@ZAL+2Yzf)h*Kw>|<#*2G5rvP;Ubp(rHp?>-7GX(+9Xn(c-b9V(-F=I@l}&uv0z+ z&!i6SNSD;&%q^S#$g~+PZ2VcBU7CNhGh@8%=xK9jZPM<)wU8A0cjpRI_|W@peBRq8 zd+!=GV(?^6<=?*jhfB-To2L3-X+rU4b?8(%e^WKWn6A%pTbx=(AzP4p!bai?)E0=yV=$&P;^Mz@$oy!$J8}xEhTLx zbzlR`qIG`AX&#%w+k7Ssn;OBIj=JIqj+WUmB6)G&KA@1Hql+_u(({i?QF0za%QjF{ z4)7*s4_#_PwDt3OCn4ut)ewheYBA`MNOecCn%g?c4IGTxuT@;*Rk?tym;hFKcfknW zNup9C7uk3Oqq{&-N+yaJu7aVsWeJ_OCKRXv*C!8NO6>gKY_5rmYqoYVuhOvtNn8mF zYPy>h#9#-0U5pXkV&us9t`)^`tirO>i$`+>vFx-gbR0avn_TXa^*&``QYU+czU62*V6cCp^b)yb3No6(QfW6r`kZunB#q5_*@pDkfN35 z3Iz(sDjR<}Iafv;f7Hs}DTW7?@WBTwD!kDyAhRIILV?~V6v#6!?K)z{&MP*1%ZeEM zf>TdOS8wrc{IXj8bM#ssJ)bF%g)FTPSmOIv9Og|mT{c>!WOcAGrI#jJ+wfIyG93>l z{yWUH8Y%+Y;(n#8ohyi!Z12BYvJA&?esbF>z#J9<>f6Cby-6+%t8Q#m#6%~yxqOBu zf-C8`kYYkUCl;jIJBF{0Xpz&!Q%tjQ67W4h|lA;h6& zq6|U3FyaLp#9EuRgIyAa%P6{cvoLfv9O#85i;RC9tLA$rl29D;oY)86gmPo*tUmKJ za1F=wSUQjfHDu1n2W%bR*zvgPAW)Bb>q5J1E;a z!+vE4P#|~T*`+qLVPCn1+0q4YkHrwQ7(^awm}+^t#_Z=R3k6V8*El}2rM9!vi5cp7 zdz-w`ZjPNyrn#(2xLnVKe{smOj<~R8{JrbAsw}}LT0%b?Ex%dIH-go7cg$S1$)=HRT7e-eSLX>r#*-KP99t%d2 zwlLFFb}n7Ze8YOAmRb1O8nZD|2d>>Lg#Gk_cuR1WJ_5hyNnCIFg3)U7&j>#X8i_-) z?#*fLFfM!K^R=?Rc!&y7dQn_L(=mDp5IU*tS~6Q{-F1x!;z&U zF{*m>&HHkjotH&RKWarB+qNLC_kngTi=|h>K{fx{z?1Cj5OP zHF74r&YG_BXepp+>vWo`UVwCeOks*QhV_QS&OmWx_10VFpre3cO7o$rUhy`oz6agBp=s^LZ7z%ln z#tQy4VWN|_ai-q|4$#kLdP&jayK7m2W1N=zum@tp?8q+Ucw@5OVp_m^4SZQ=hidCi zGceOILq6|6U7#3-%9*B87@32`TvLqhvTSd&2MCN)ZIz#A6s(sO$4KJk9+s|#@6kEB zqKH`)=+8Qh?yDbH+=TcKXjAIvSbaS^o8+m(5!l_m<1;`fbt@YAO}|%{p*wNfmh7$$ zuyNLiBS6TQwZDSl-`P@pB@ENeTsU~8$-h`@f{!ZORma@sC;1??D{A=Y0Cnf}+%4nUqt@Ebvp|uISxGS3|)qH+ovRmbqkPo=IW_@h+>@Zz&=t=T&KA zV%C!QK-!M@hyg=_3QJo%uqKH$a}Y}V}CrYb$Go|>mCaWwshlXdu=Au?_)(qPw9!kUIfx)ucM5$U#IXA7~V z#0Tc3;&KtVr2;l~_+cs*Vs)TYuy{VBo)tyR$m){cLRPE$N2p^A{;6G1b_v zGOI_Vbf|zSfsPUr(%;&XS3-RLX7X*0MKD#!Y|g<*Lq~VelW(xQ)vfGquSRRb(!`X3c`iny0U)InyV5^_p7FjC;>h;^fW`~*0YFJYqWA4Wdax{6tMA?$LVK8*fDa{-v#Ex<>^mcx; zw{5mDvJ=OYmvNS#hHm5cywT2XXHH&splyYR*Vs8UUHM_?omlu=;SKuUCehz^uz#!$ zTuHCP*AZd>O%>~M&9rmwOe^PfznbHes1p=VgB(7m39T%H*0AE*Rn(wD%ZWrDhj|1& zWd9A`e%U*0xf!;W5oV|x4F<)xFZ;`~ue0K%oTLQewNLsl=ZGkT+e-;F7-_c^JO;nz zWmQU>7dOoLPvj4ifQ`doG=de|RWL_}Nv1KQ)<)=mUEM15iEQh7J2Rsh(iIx&bq^D_s&rl!ZH9B_&#u{fFMU05lvgA+8N$O$6~axlAAOS6poPve zHZ-i{Xh2s~rqyx2)o|OFw;@MXRsk3~!b^(E7+UfJKXFnSTcxe=@Lem)NJ&1L0jHZ{ zzz-^ZW#!uy(?)KfpuDIwzPh!(qpi85PG|$}BNXv8k_^4Me^=fFPoTBVMBMc_eg7eA zvT&K8MfETyVZ%PsgHi#pRA#T*BH5ahtyM)1X=T&ymXDvM(S*hgv^tNTk4m>y$CTy_ zpH-hGv!ACeW;c7I%hMjaPDm@~RWxh<-hY60k*kuQa`fQQ^WW!Um99HYaCRzbWG4n_ zGB5DPrK2(;?wUvU^s@Y?z1@hM|C`dvun-KJHDE%QBWqnO5ubjdo9Q88}1ci&+ukDNy)Rz&X@^`5J|7-z;bKqTVd8@o~Ru~^eaBc_>jgWpeE zXcdi~v}Mw8)}?BuTmJ48RQqL)R=5v)+hyNu851Zb{uvt?WB?T;hN$P6G(uQX+q9&i zZbd6ldlPv$?-XsRcHoWLGHKO;jCg7G1DD&l+1pOO5^R-QC?PX;jYH(zBNqDoWdye( z*JO1`9_p*w&UIZzH?!YWnp(wE-ncaVY0P(KuV39KV$8lE0)2L^J zLAzMqTGfA*zu6lnvI-l!Naf(6`$*}F4zrAEGG?Y0Qnsq}dc9qx@)w!7i88yVwVtlY z9Petts#%hcWoceHQwRP3`i3f~j` z+$|xuO8UMV{3h;@F;J%si!WWVR`trVnbW1&RM3~2iWR}ZZGdD zH-~c}lvWz+-X)l_wo~TS&*yMU)vRQ!dp;vF(J;En-274b6|NS6%9q}B<9lKa2pO~C z3TUX#+NpmQ{F1C|Bu*NZaME=8uqsqO;Lo_%6H>A>9v1+$?w#*@i z%VszhFW$R|%)9gf!@mb&O)pm5fb`2nNO1hUa2PHBYQP_$y*{FyegduYOKC*!p*`ER zUjHn7p4Q-5wEVVN)9r6)UEPCL)wwjHoEqDgSJ9f{UT?X!e=POM&y=glIW zQW@_;3npZWieY*VC52sx*_^Z9qL8SilSc~bZ@GI5R6cD7Q>3zR1534wH(B_aj`!?t zKipKiim6Est*7(7sU?!lw4<8a$pWrJGzQHxC)W@_11Cz4khM@|71F5ZmT$`z@Hm-%-nujy>vld$5g3ZCsrz20@+7z?e6^&@T6 zM+l8Z(3{6OJ3D;ojjh=)uw%=pKfVgEzygt&?c5Z%4FmXa=E+XQN-p& zrlDij%8?W zpn`!;#J|HH(=s?Q{&6x-{mJ;}(qLFId`senKfAS?=!ge7g52z+ik6C16`d8UD^966 zyW*P_->Epa;(HX+zF%=s#U&M2Rs5{tmlgNqj>#RHI}SOlyDRUie7N#Ym5)_EUHMAo z8r*eJ1A|K|*EC0)XIe&5frhHFfbm4P_<%R1De<(aqc(CwL;gA0I z{z<`}L3J=2xsZkcHd*-n@W^?TWPN_br6ZBy%>1gxM#MAagCZ3y>LGW)fq|b9E*pc3M#$tXv%I zM@V@+jcC{N#irH`xgJzOCL-&!j|n+_(j=U!X{c;Nc1cZ>m(vXSF9eMGktW) z2n?-8I7qTV=bIGJrG+byzd3_e!0%EKRV$#H0G~o;M(uyE`){NzfD(~$`M?yK0H@LZ z=Y(JOqWy2b;8U(}lM1-3E()}qNvogQ{IVuLwf9|X?R|eWNtAbxJ(1)Iawn;z$)s>6 zlP=lQgi1ah9vB`%yWUKsNYt7q@sZD^(j%@p@6zyE69~B%d5{N?1CbcW3&?)BRyzrO zsLgHwQI7!0j@?a|;~+#hs;#ZgiEK0?tKlRyB&Z=V4Or+=NkHQgL@|Dj6vkbMPwZ-f z5{IX<5t4j38=;4vn5;wEj%LCOV_bNS*uuw=QIJeRC!z+D8*tJB_aZCs9}@*|OO-l*=8{zgt@DIU$17PSqwX!It+QKMP~os8rg?RE-Ka<)Tjy{KKvzzuY0 z;k##f+hFCegN^dfHm06l_<;I9QArr+FDaI z%HUW3?RFd-k-CvUtLUY2N1xPx||M z?sNc+*1&GwHcaGfs}|O~GQN?u9CM%&QIpB> z_TDH))RIdZQsyC!&)-s?!%K8}tP4W4NKW*oa6kkE3urHj)0phEJ&6du!5hOn*uUj_ zjmN-;V|kjn?VZ&eywueVOvW<~?t(fqi_JI&*~1Y{z2_y$2kLb`fkocm^%A>e2mei{ zbl=?bRdg_QcGY%tEnp#;C^Iinjf+;#mab3EF_|W#+743p7QQPrjxjz5X*F@&99e){ zO?|)hV(PY5kJb=xT5eNyI8iMrId59Mrn$3-MD;!BX*D=EY)Ko!mN)00wwHHEp|QU- z6*qX}c}*go)c~<6JnLS68y?I?s2!iEq;FfO#-*D^0i4y%2MU`WY>4%We2+ z;o=XJvMy|FWRUgYx?azIM243AXf)5>+9?(t+tmz8F06?DVuNo8KsNY{rE9Cu4zF3k zQC4Y#0@oe-Dd*C)k~nHL>qe~H(frIndrPTQFQ^1k$^j}((FLFxh)-F+^;gj!XPM7u zbiu(nUKMMD1XWaA%laR;5vl2JYT~}wJIdFDd-`$TGP7(csB9aq3dzPpX{$%*43D`48LyeEMt)^D4YYgnCp}A>=vjyY4L(ro=85P=ZqbK_tR89JGzeKIFD}N@6h{vHsun&t~;~|Ja z;}~8TUKxMNK6GqT%}vF<9P5HfIHtL!ekKUFZK7UpRK1)+$qNmgY)cHyYfv%Q3!NQ1!NRYH5+HHMQ6OGritO1sviR)X$~`3p;JJ*?!5Uu9X}5yBjdy_ z*;wbr=yK0#X@kel_r1sKS?8tn3*CN*{z_djqZw5<^4IRn1Y1G;WYY^?$k@&7uwvUr z*y?!nj)r!gfxW4Yl+_uR1Z~yPUc&X<(JXe$Z+H`0<;*+hWeQ|2ofpHv&oLciqE(cboTNU9YTz{Qa-_8*dl;ZR(ZY=Z9Ky;y|j-W?`1K0qMmjn&S2uMWx&jZQRK$ zMeEB%33CAL%YCIj>5XQF8RWWVBU`b~Hr(m$fN{o7IE=51eyMOxOL5&DUa-8IU1HDX zd%r`Scnx~J8}rSn%W2J8vTR$d)Ptsn-pf0;wPy3*_fKyO4={5@8%50GhttgXScK_< zhrSxSF1R^6LOo>GIyiKjjYt`6Ix2Tk{-fc_uw62M(F^gR@x}4|$c5dIyvAmsdESsu z=R)#GrXCk>6W?S*U=T2hD(Y}QW$+{L| zVhMI_={B4q+o#w`Q#QDxw>|Tl;xLA|3fpU=xzP+SGgryuK9juS?O?xiWuE`$hp%!d zjm4?mo#iHKk{ed*S(4$gn~zoeP5@S8kVVk}X|JkIAb9G+wZJ9VXIIoCEm!fx#iq7*_xHv-KjN^j ztghSJ>LraG)`(JPU3x?;a?3M|y`;7mfa3`*2-F%n=Ig)0zKK%@xA8`&-pK_w2k_Z< zZIjJh!2$-!bwjU`ZsuLX`er#qyY4%-6f;1OIbMGa2a0#9m($`*TQ5V0dXqbevKl~v zxnkF>Zq9=&5)UPiYj-RfW`Q_X$;JAeLNcRl1PhGWsUgacNA!ytD<~{_VQqc=yuA<5 z18v^N3z-s7XjiT_H>SvICSHVF)2qY80zBH|Z>YB6UPw!5cioEOz;GRc!`KbXKC^88 z4$1z#clK`?W?GY|k!JQKbuy7!Ou3$Wg2J)>7qq!#{cWi+`RgmZN%d{r6vdXbEv`Lf zzOAY*@(w&uV(DetmYVTg_+ns!Hx4Ju*>3aOItkOPLa0@PSYNx1pA{4ck&FRn&oaTh znTQu$0H(Ay*HO)MIkdNRcI()lRqeEQy18KPh<)uBwQK&HUu?@Y{)ewi34x6RcVrW2 zP#<)j9tW)cLUncNPH+p7r3Wa9Hb6s4NfJk4TeJ+sMMezJ~;}o(pg#fI^ zh3z(cz594O)z+WX-DzN`8c>U?%K1Zkjt{Yy+?qOykjLdLg@*iWue)A<{G#TUJRb+@EVS0we=mIS`LrG8ekb(zq;As~}hcKf}++Ys)PUJdZM z!4a0_i3+Gn9|trMCy6(zwc(Vdt%N`vE32{CxQah$S=!o6khp5U=GEF01Lzc#K5NWA zBY{xpIFk!cDpQ=zPt z=Oc?=g-4-OuJ;~%)vICkn(K8sUF|C7T)T4p?>H99v02jC z#qBw7Q@+7=wt~eiucaV#UT0^wCYhJ$x!592cRrHFZ{%NGj`<>IN*Rqa*4hltGcNkz zL0(knYLJ?--Y4z0BZ)oSgeoK6g&l_~3P)yT{3pKI^gVAvN5e_fymg>tgFA`J-lGtG zE>o5Awky6r>xy8{95Mnc(6_a6Y4GcG2~Q^xn>gGqGQett&T35GpTOiz3&0mRvWMLx z3-!m=yM>!J@Mv5HR(qp(?;<*Dv>t@W??$KkRl)WD7ucM1W*D&@y zY&nE|q^Bf@&jHa9Aqn>A0zZ(F4URh|O*LRj>VH{98v#ryXV3!wT zlN_U%I}gCu=HH9(ngBg&Rn?|pp5i{hV6bt= zm4;f+k&Uz^G((p|SwtYwTqkhF97^yn#P@2#&&7KgAfzns>&BnY@-#JAy=zMBhhXN;? z>%M8`He7@D(KP<1gcw%AWwwPf5XMIMYj$e_pQACsmRa_mg61+g_W$!A{mvZkJiY41(y}->j1ziR=6g~8Qp4T%(f|4hZFfKS z?|^8h(+(a;Pda$kf1VP}#nNB0VvFg6#plI8GG)FK(2Ty^(ejdCSIq_Eu%1+c+NLJp zQ;qJm-c)tf;>*cv!I#C=D$A^3c8_se&}E6vkQI`hQ0Q~?>O_f`19kM^e(q)eA{v@* z_a6;^VS)eBQsB>;Xl`^6V;*7sny`UAkS0UzY52!O4Svn@+ZhTyAo%cT5=12@Gsut9 zUZ}!Bg@c7ix8jg_ba`!@jfG#E$h2GLvM41Zv3lX`8vAsMIFh|D4WGf&Q;nq_ZM#p_tB5>l_PJL z_YPL53dT0Mt<`lUn=viU0b?3-NZC@alizh}3sLKtN1Iv*(r;0oM&0`W$CjO><+@AMrgsWTet4`rc)Bch@)3F9FAJtIbT&w+>1_OP!dl3c|u%b&b$zYT0 zw>&2>zgfGSCPjVU>WyF&)n`h&*F8)sk5^@ ze}0ACEaU9*jv7Vh9SUYG&z0s6rdYu9Y)1r`v6cXjy##bOdKH%o2GbU32rF-vk-Vs2UGX{$`YD1?RJ3>y4H7l zVXM$tXL{cPKoAHm`jrNFXqtn)?R-Uo6aimL=gqP;UF{H0*4hdeI`3tc#>UXmNLVd7 zq;A0#7)vXE5wP3DZJlylcej2azvi(hh$Ys}fY`F3y+aHS=5#mZ88S>EJR-lzt%WiC|G-r|I5?jrx@ zN}0NQW$x2ev#{=oZJ#9qnH7>g;!SV`8LnK8K5r)3WP8tPL%b=Kyu%>8;DR&&w3YVf zgP-!Y<4*Hy5n@^4w&a|)j#NCyc{oer#=3ZONy94FJxxHCRvj&Nuw+o$2lmJs#(~Rh zhiv)9I{JjT;}Pu*O%|ZAZ}>ToN7xBkPixOA^=DE!DP)Go)>=z`*5coRrecw(^eW16W)b~!UM zw35|pz??1gHjHe`!VWZD8%;ejm-{u9f9eBD@@KWpX;w=sW3ll7P(-uSLfkCoIMf?g z*VevvpIK15n;K-{WZX6%>g|dlS_A=;cpv_>WRmc?9psXrx@91??!S4Wy?2JR@a$ue z?mwa8vf$+Kfn=!4uZpV1R*kEgP_=W_2Tip0aEA!Dp%uo4W-8OOblp@I-tv#IU`1t1 z^FQ;cp1LJv;7gNG;JnCfD|XD+g;%?^-sajdEgD$2UZ8AqJI+{Ui4{StfL*Ow z(cCD!nylI}IFN5;G_!WGvP^XS&9<=tL@44b2GYEHhZM$}O(ixgc1mMHT#$Q^m#|-` z&ZDhpgTIf(tJ(_`zS0qOUW!+RyfzMVO&UoK)?jn2T&BOy8&}&d%n7x+2AgI#^w!74 z$>g+;>8}x*vnUVyH?u1BA6WoV=Uk2%9gMRbHG9(r0uHCQQ5uYEn!1xCMWc zw%A!#x*?}XBdv1-nzd(msi$PvE)$oVVUvcjox0dDZdxrZvq(9~pcL*c)tXWtcm zM;XLfH-5GGbieGT9*n{ZR@1AV-cG8MrUo}v-HX+Pp zI@--@0^@A$&ezUgW7!zCaA3X*uE-fow1$uRHdxM)6_&_3L`;Kbp@OLvBCI&=zBFJp zfmAax_T66KaiB-lDM5le>}F7iGi0^+9ahF-Z5OS8=gfDK-ggj~n*BHXLJ0`pNWhK; ztOG1`Fr*HEyuceT`v*i~kQ(JqyHGz71&>r*qq@{oPU83$HsJfr&fMf=%U^Ro z9`6%bGJ!Z7azlQG`=8L)3ickG9DtTr-=E{2T%)hYlz$Nh;TWNjIQmO$2;(-mM z)zW7k2QRj%&HRD8TEz=8Ys`3RX|=lHR#92P_Ru|;QaX5i-+xj5NK&22f9&n#A?%(! zMc?1e$`w)LjlXbZ*QF?sHnld?8~mkF$Y(Y)LsS`TYvT5aS&LYz;1{SlGZCg$HkDia}uIt;Hl!Xy4 ze&QX59<`-vEJe2lD!l_M&Z*3MAK`Uv4-)3lWit=U$%A9`d68w%Kiok88XJ%T6@=22 zgv}zUvFulaf0^g6swK%$Pn!*3Kh z`U*F!{nwtnpoLxWNd8Q4Atl_4?9(t@l^!p7nmaVmO7FCfTD);OKh<-S=}+Gnh;lu5^v z5r=Jm3Y1$Cj4ZM^hE~)v68O-i7U*k1>eHg}X5|rJj3rmAp=X@Gx5AOVmPHuj3@0v% zfTmHNrN9DEwTigp9CinAB6Kd}0?DX^-gfxllnX^}B()=T?HNX`yIv%`g00EeP&<{@ zy2T~JD+-+!32o&;MLITAAnRi1(dpv@+UBG6V$W+0=dAQL`^Za==3-`53XWAn6rZ-XfHDU0|Ef&fsb2e7IvKQI-Cumz~ zb<>KLnvQ{9(I_2Cs{K@+;LF_{!+uNQS$^GLn^I7$sKdk4C@0T0;K3TP%^ z#%$yZ!Z(`$bQ}W$(RQoQW+`2+rf{i^a~j5Eb*I6cUYU%>ajsLqwv25#zjnF!8JcZd zZKIWS)WSSnwcPCyP-@!+R+b^xQfLPR&|vff2cnoIM%t}*H4PQ^iW=R?6_pjfiOMg_MH;0r@&id!pg12>1>N};h)lRSh#Tqh>7p4D26)MUrPir-fJuHx>B`zr3Q_+!Px1fo@q z9C%W;u^gW$Tc$RjJx>{uq-j#wPRs$y6IT5lx|r&((FW$Y$as5a8$bb?l+3sdHOuT~ zc><`>Qtqb{P1J)eTreN)$Pq|KasbkVw8GfkK>@l649{HTz=axt`E70JYmsqsfxns2 zDDGYhQk=ETzg0!o5OE$9Bh^yGgdtpa#aWH!?%o(dz+%FovcqnzQ2E)_Z0C%%)%9@ygl%JB&oXPF*;7np7*!ui&`m9h78g+mYw4W+ zao#s;P;yyIW1F+ke37d-qGGC z2M`xe1%ufO=a})SBDq)tqGd&|=GJZ(;O65C;y-i3?QJe9tZijyrT94~gSFYGu4Mcf z7f*2WQ@x3lBr;P@KU_+E8z(qRr4{;*fB@OgdxKH%B?7$jX6fSaTy_ z@FY?ef^4FZV^&}^9GuP~S$CU_aCK+e4xkqr`jo4lQ}$EqSO!n)8v-77IRnkP6^mAM zP{Vdp6<>z5ipaF(H2dKOcj!8CU&YIshdCzE6314vQP|I)?v3kiU4;NlW3wKy#?c|w z?84| z;v{(@d0LCC%zmo+!6!@W+ZV5~2*pv#1}^u;x4WpwZfqhz#Ows0LPDtm0>cT0(!LzB z&z8`@aa8R|D$4L+&=8tCsYxzZaxzO*5kB3p!R-|@w@Q0#!2R7LQXdBi!Y|J9T?SSI zSo9WI?KZ3WaH8sS-uM(@$qd-^z4bs;p&7_!7=gB7Kq|PS?J->GJciAh^v)DPoaum09W{p_0cUuHeR;DN`;cg!91=g%)vwNg> zHXXpPs_(aAhurSDrd&I{xC8k$`Ev_}f?o&A5OwVQ>nIfJ zxOw%UzGtjN-?E_b93MXkcH%D4bUPMa2f|nD_`38U_~J=)9Nd1c$PgS*es6rA^^o3& z7zu|;s}iE1fDWlT*MX_M;?)O_1dhjH4T@MyDnBrsHIcu{_}A%vV?PYs?1c^Lh;EQu z?j`mh3=!`Mo1=}YrJcopTB@pziJ5P%X~V@fcR(R4J8jE5&uyto*x9YKT?~E7EOhS`Q~UKNdFhti&fh`YQS~WgD7{QEEsg?*owS@h z<3h6lo8Pf`X*P#zWdqs=Wyx0KG2qPYs0lbH47P-csBl*?;7vI3NTLkR!jEdG|& zY9jbuJG&KrsXGCOq{>=)^;@8ugqW|?@IZ7V=aSK>#B9^L`Ljd#yG;_fOYB}^GPB5K zJD(eiXq9Gu#TZ9^g;mdf$kFKjX}S033hlNTV{N_NL&%_1%=Q)rRbXI`3az zkNNjy^oz2)&GG8D)L%ub)@hkphFlq+8J`t@#mcN!M}g}z{H|&OQjLahGtEn$rFVt( z6DSNAVQR0km5ys1=@&Ik5?Nz(E#t5O4u2B<-mc^rrO>3wgwHvfda}99K9(q1-J7V2G?kh%f!bu*jXcJ2g5z`m)7_F1vKF zChKRJ2C$VP1P#u36kFwIm;lNW6bx{mB&xahv#ew_UvetTncTD9Vc2m1H3qbD59YqzfSKH`0>@MXhd z4sV9EZRyj{8Q%7F;Bu6LAW^WhLGcwYvDj7UXEdoOXp_0>AO%QT-P$nWHqf&SOH=eZ zuf7`G*pUnL6>LT*(oGF+U8N>nRA2=zit_j_gRX1=rB*pst;}FUF0%0{2_6_StQjEX zk%?#j+X%X3u41tndCQf|A8tvvtaXAF?8nx&M?$FIdVPGxVM+-1OSn z_)ca^fBuB54^s|!XU>UEqfcmMrVRM)ScD9n;-m(x@AvuHD3)So%Wa8-Rl8JusA|`$ zgR2g$s;-&=b7z;#XqOcL=OLSBF4wWz7!EAJeyjq zq9=RN0x42c;s`Lb43M+qW$f4-+bQX2ji(<9-Ykg{&4oCT6l}ADD`9M!Y0YfB%5Nnb zKe4-Y3ur;N+!9()%ng!P*HCXKq*;7J9SuuJ_~mlHitdUvUX*6m_EGHBRqU^*l+mE} zMMQZ7h=AExB7}Aka@=0&nPqVb(FlWs2iKJBjU!PZafH=S&xMk2_K6a7SMSW)F>MjV zxwXOB;i%|u(OdEE@u%Y7a3uE~W~Q~BI;l+=4M#VDo5cV*F|ah5a8X#5k&(;jOgffa zeH9>2s-p&4S+*)MI|ZS@zT##>G$*W!Cm=AJLyADj$LX_A!yteC`INoy1? z7rB$po>shDILA2Fi(Tf_mbPXwtd{_O)x)Q;L$NK9i|jW23ZdKvEJS|7op6In`zT8$Bog3?@-CYEK%gY%=Uv&@&U_iS|`0?TcCwpUPpiv%g z%t=FgA>EH>!xr&1bFciE;oTNCE@pJL@x^NFY#Mm)wHAtQc*$z<^zh*l70qg^7oScG zqBk87*IiqJy_Q;gV7hM?F*cZS_JiZG$)pXPSPYT!@TGWRTob>QYzKY(i^-{W z+SHdgZ%S11ub|cat>oLuxy7U2FG#*`h4JEma=nNq@cm7NX?0AZlkyDX$BEyol(lc{e&inPH^(W_q6<4bl_>Yl!m@XLX&N0mRMeEyOJ4&Rrvg_sLN63>8|n|I;9kU?Vv6;0rfg;z{^2|VtESJ+yH!%_z195|GftDI|BIhMOt@SbLv^P<)J z$-(1=*@Q$N43~M^-m`6`xDG|SKS6XH{hG5Ne3c({jo!E1k1z>aghpCtj-60^Z=MbL zi-c$b@1^(R5Qw0)$&;#dXy%P#6ftFU91To2722~ApV@h3Lq5W`td}(}n{7U?4 z{962a{01HQuP1LLe^1^_-b&t1-bwzEyqmmdg?6K=+FNh>t+0_I(x6RL>3hbF@f8o) zY~;PQxtD?tWNMI+asBFcLqGSg;F0)-Was2>$-ivQ%NcT74BlxJr?-)Sm7ok9T)k9W z8#>Ei#<5*(i*Y91c<`(|N`p;E2+m(v=D|5lLeM}Gw5QN<0Nr)uqEe@a@BvpcJ&H<0 zvuzCef2Y`zTPC3f_*QLAV*9v=X6Uof1t?~`&v!m-eaxQT!IA`(-mSuIKurjPeXViW zUv%7cF(O*kuE%OgISFZt7FP(!8`c)SfW6tB^DkGKd`XHb*L3qI)H+;e(%RI-*VY5Q z&|shH+H6F;!L@Eld!qH-WI#wyCC3r{1WBwmMD*BGUVl9;vx{R5#;1N^j;-gLingKI^;J;Pw&=*J&VF z-GDcxZXjQ2R!KurD7S zyb#v3&@6lHS+1j-`{u1!3)?|V4<0IooE9;usoU(GZt=>jwlss_?u{DSTBC25_wX== zI@jI8d>hx^GtJh>`)CSHt&XSfzt3C>#z(hMv1WytG25o9^Vip=ocg`stGa&n;bKbS zcuGp#@hnmjh~A%bm(^c0jM7!zN*ALHU@?k;+$9Am0#)i&9c$tCAw!5sA|f@~5W^0U zR0ivPzES{Zz3~LFST{7E5Ctd+jJa$`v%cw8!(D*RQmimnh+6F<4Rq=fm&s8|#xuOk zo17U7q3kL2VbR0}gfm#9H4C+Jr2ed{Poa{cL_)9LbA=6dw#E2!`#TJ{(j^=wI9Ck` zj()nzf{v^J4KiB0%6`25*R}v_7!4~t=_a)6k7>!2Gi<$c1r}2ka&VkEur%!{qa+lP z2uLD~5g9tlN_Zq`_Kq2vKH51Y83sq4KvG87; zpQkMWGq$i}CM&S3K}$;tJLY5ah7KKr!kVNj;N9z8*ZX4eFDIx!rn#LO0pq2&8W`tI zAc|tfog$c(&@D=Q(KLy&EF9jLnsw*X3yip;%CIyBg$;!f%m>NVkLMy-0q-Kulwa&*0@IBYCrSEzQd*>l=uYG9$Kgs1LI0ntl> zUCm&YHmfX`j_o$fm$WC{-ga)BvnqfD6A9V5h&8`%deYm${h;LTxBLkSlhq&%SaT?Y zUL{{>Dl}Vrw)V%oPW8QkkY@lA@3ZMFo71g);R50%>ZsxAX<5(ua2^KY9ci^PHVsP+ z>fBs{2PT~H771%U>!({7u{PhIO(&oTBK@SBH+BjguZ=Q4a7i!AXGmM{*SCnN*i zgR*lTMdhKbI&n-hEP-<|#$(}Z8{wCwGtZq|!Vp{<7tk2l35cR-3fKP;u~+t-3=c8b zA~e68FG!j8*F_dTBD_*#~ zfqS!&<+Z)t@|TBqQ9@p4YgP_bL}50a3>k9``$7(-CS#PT@35#(tF7;h>@Hq%ayMlY z#i{zUO}kt4pdkZjb^2kp!NCYwF`MhWF_wygFjx`Rti<6 zor4Gf2c#lKQ2PY5C9kNsa-^Jg#SntpOLE5}pS?DB8q(rl$$d3fE}eaG?vkA3vmebp zj(qk@CZPRR?(N)vas!o7DxQ5ZCu859za#&<{5|=5^AF@7%l|q5Wd5nV&dGk(os^w_ zA^&1w>=r`W-!EKLxVUgh;Rgkzv9zr{3z3?FcX0-G*aLzpF(U8J#~ z$*E{5lq{wVcRu`Kd{F$)jgGGZw^Fqhh-*} z!s+O4z@K6irH7p8jTbqWK(7;+3P3cKsQr^S5gIlgoIb2sY)Nw;x;AXVoq6_Q!IA3? z9rlVuN2#6)-qq;OW@hWWXa#nrh7dwqCl7UXA0w~Ifg8Pdra}>`tF!(39!ou;ow(wG&XO@Piut-6+=SHie z0mv;O&1>s!TG5D8H&>pM2d(d}lWa4ZLYCrhyu@N3bvEiyBkSvSJotRr6?WT+PQrf7 z1vuY*S;fx{+A~i`T{}gb?+TZj{a)G$^V3A&(q0H^LJ{lQU3Z{dX?hU)Ty&4XNt11&%?} zdd8P`tW}atS>D07DTZjZ#;T?kg?3Wfb-a?a93vgM85Zkvd;RV6;dqLKMqG#7Nw`oSfqTQd=uoUZ7YDd*lN`gu^fvw)I4?J4QQ<)oY&*M zh+#4sq_$@P3D`5d2ca_`pWfBB>DKP5_RJ5IF(6ywri5m|X@>1Hpf zBhYXd0h2}^2r@YgDR(U*NDl#%y9p~T$1UEDu(zty*#260&d5YRk2q_&leVvn`2qz+ zUeqPGz)mZp?T+LuuWgxMA1ntD$rjq)FkSLrDcwyAkt4a!OdCPbJUBvVit#M~IQkCVN+&x$ zoZM!DO(zA*8s`DsqAX0y>Tb@i84tj z{3V@3<6CowjSsnOB;||oCRADE!>kLb$UE=ZB_lwYoLWPDO0zIafL@_0A2Tq~MrtS} z*LS6+6WL}+Ct7^*QB{X{1>v6p;YOa1W)whJaFn2&iaO7OEG}40*=8tW5u5w8-i7zm z+G|(O)#n2ykXaNY?NFA| z877A4I&18;On*pGtl~R+mO|k_!6h90awmC^z9{m=4)H$c{Xl2+RJ@i8bMtbGa-Xie zxAJjL!Fj!qFYMxbkw0WCTYxd%-nuWol;F#dk!DoZj!I|jSZOeHx9}Yhro*v#8 zT@qau-4)#%{fVPwr^jFBWS4Kn-;S?|Z;5}Kj7g>z&u_Um8K|l~zue z=60^)WJg;~i|y&nWsO!8?TB2YvvLcSl`mAjSoxC0ZBF+EV<3A~$X}QLb^gZq(BxQi z?tr8EI6;+sR(?)?ZhjsoxG&3pTBo?jU$$^0n`)O76Rp^uqd*~vVrk5?tWbm!34EC% z4S^ei=+gYyjK1~hbs5#a2q`s*p{X;_Gd3-OBd5aH?ZlKn9Fki{Nw@D}FKT3NRlOv} zS64`eQ0afG*XqC0bKE7kY~fNdJr8wi!q=+jRqcP95_owcH$J)c2tg{ljR)E4g-D^j1kTIyFgQbaP zf|Z#hwn9uWcv(EPvDbEJAL{J}S32|^9HNH(oWf22aHWr|c)`p&pUz9dN)tGAR2%)u z4NDv;*aqZsFIv^01~9WZJ%8|G{E%z1;q^8lh0UL(4KIR6ZSr{7ff{c+qe+{aUecE0 zD5Wz$AS**7cjV=Cuw^b{nudQXwXuqOv-YftM+}342&C>mev{AD`SXGcgNwZFnmeUb z$qT9lm%TDPDX5I^N@|j2F0H9+UqEIY@g3N-Z1Sp&lSeMvpKsSwFCRj-}(AdNIXh4fg!R zmX!9ONWp2fn7_$Wyn4@{;-l6BfnBO|R)uBJD8I7iKf^7Ipvp6{d9}#gnH$zKY@Woj zZp~; z%l2PM4rJl<`yTD}0hwtc1=9i9N)ex{^xdqJwidOucZ-+tzQ2)fj>2CP*}!uHio2Ln z1G9^_b8!bz&fOYazy=)%^bOOcW{v7z+IUu~af@vN=|*VM>^2rCuc_j$9~943QIP6H zLFO=k`g=DSP!RS&RY{!}S@B-xZ0K=|6D&1gL692ASGy>X1y#ru9I6`KWnY*L(z6tD zSLbizoV+{vVjOEtd?qK<=#CoOc#ln!Q=D8_l%>7h9@wR%v)aVt(nEms3!8-23kyYH)6}`MKx{#USA^GCzO?{uMLM%ZW@U=!l#?2? zQ+uxiN|y@2mX6cV#?oOQ+Sb$Hh?`fN?eq$4thCtbybriCzYuLa046b$M~1W50qt0e z>0;Zu&|&BSA!={|8s>g7pNpP>pMhZD+PzaJKWE>4PTWVYym?=5l$2?lOtBeTFkbae36j3$MP?Yut{Fs!ewsr1S6|?PaOJ{J%K#cW#3TG}VkMc>O zFM1$)JdR9m_J_&khT(B-H%F|CN-=AtRtglO9y}hV|8aBF@PpiXcFoX?1%65ucJ**n zgK_eIoRk%XN?@$43Xs8Aj;4@(j%0uRi)fQfRaba8Ss{joCz%UMY; z`(r!6Z(^OZ^j4OyFM42V^On*Ub+WSZH1C8?R;(o>ziiGNVM>6x?o=LCuf6^pudu4k zQazgPL=4rBO^O{WikL60gCBw$4 zPqfNdq^H{fYy@)-*sruu*c-we+!HcX?ns^#5Y}?Y;)(v{c0CCa70&_T4WF~ZFUNs8 zOKpb}=)Puk5sXS3hR`-v5j~ULu^@s11V>xtK1H`Pt#G(RvQaZ&t|;VicIR~L;(32c zd@+aK+~?3foy$d_mr)qBZ8rSDo8)$#IqVUSZ$(@d5M?G}6;Uo6s1K8KiV8uv4|hy~ z1Y|lHNt>T}#K4$rJMT$Pm-#Ctn;JEhqh0-wFH0q9rL=}j4R^gxWK~0vmN#9!xT;V! z-Ug_+JMB)K^biCtE(AU-yAl?e_H?ddT7IQYAXbGsWc6q%P2adkS}kOQ%pJJ}qlvPGQjhDxi4EWH{AZPrm zXzuKwiZjTwjyN@-ygxugS)J(>%$wyL_`?=e5HA&3ZUYzSGAeR6tZ{ssz1iPPJFPuC zHnq@;V*MCPOkY@mI8g9DvlKJxH}laKqRNsk(+2qdvSY)8vHn|iZio?IYF2c2vDs4a zKesISwnM`RFjmzrDIqTKyJ>c;C1|l;NAA?WlI6y-%uf!U6V=U_{1ar`{|{wv9$wd3oqcZ|o%zUi z?AUPv8Au5wrL=@V7+QwPvlCBP&Hw>|ticwRB}KBFIFPpkWhiAT@D@lJTA-A%1zOrN zl`s`TN+<+qdzC_gGS9@bE$jQ;_j>j|=g3Om>-&R?`0TB{pZyGLyw|<(`o%i76I~Rt z9NID2XsjfmQd<;-(78TFjzEbTZcPWYjHPY?qBl}jQBSwXd{UcI z_*nrlyQt3CY3~P=}<(#&v^|jInCj; zm}q0$rkb5ytdWfg##54`CGd>_VR?iz_Ch3`_&Z91bu2YYXCO{v7}vVUf7ikyf2BI7 z#~|q1J3Xtjtihr1mLS52u7}&Kef-F5NwW4764qT+t6me;1ebUw_*$T7IbtM{lv(50l-<~ZE1VP9(i?pYNh@6~i zJ6^qcPa;M_rAr|@VUTSY;FCP~T6SkJ>h?Ue=gRVs4>e(L!1sB%p62`8VLRj3a!s*A zM*4I2J8GA%arWPrJq+|LQQ1`3hx>{|oZOf+pbXu@-?Bb2o~W`v@%HzMV43+O@YCkX zvz$I(VYHsP@`EZDSDskeOx{LB_y1M-UUfN-cnE0eb=9X;pGm>T{_0HiQ1!WX62sHP zGT=Chr#uCNBplx3)!2oD8G4}c+6H{W>Ia)P9*Gt32jb6PzO&8nZ$O%of&#T#YdX{O28X_(G!UD6y z@X)R{PdtIk$X(`>5<5i8TUQk<>!ebgi?lY`>am$kG=t;mODysE&XNbZKWUfejGogT>01PC+NzuqJ9y5($yJ#8~rD)ufMgg5k{FA?-9k%jRBl2rbC@qqP zKmR<7-V|MJ3mpE2))?m1>+|tzi?vdmK|Tktcp=n|J>Dx)WD}Lh;rT}|ilmeep{yfOA(p8i!)@q zeAR~RT!Wj$Pdd3jG178@I7%Jlqx=j)R;SKOMF0Hv93ATpq>eRwd!-V!e^*tXM(9E{ z{Ej!mBW@mWy%=@2BF409Qs37xAkFeFG8t058qeIby89#Z6aA4fX0KO>k>F%RH9cnl zG|>$=c!9X@$ct@mw^OOQ2^I}GId%uYq>d!CA(cuJvQGg@IJnT_RZnzE?#DZ8o)q!M z0Z*ZPJs9i-6<%W#2gW0SS1+He^bn5gtu(5itKMCIqh-8;Psj!R0YvYzZg`47BA)vP z+fXEaaF7V$hN+oIz-q5O*xMn<-;g69ii@*HAi?-%Xi^UVBG}u1o3ok?tE^!%do=d@tQwYNukRm^UVNiyC6rZC## zSlB2EJ3wkJ_P?oP3pOC0BcI65=K_`>0#qAwqtgN;;jFaZ2zVF?9F|D+ht;1tN!|t5 zYro?Sgoy^@i*tL)=}1Bt%+{%UM4V1S*|Y}JyT>q1r^iyxuh;DM@1}&r?h?IA#k(y8 zxYQ*zJbmbL@PnI1DEj1Kb1y|&$`&kacul8Tr9kcNj^^-EqOCpfoRMg$lrxyBnYHwZ z@ew+nOj-i%)Yf*Hv?W!#*;d;=A^X9VD_u8XtGx}_AU>2_k#@;bJHVpkVgLRe`{SH@ zg^yj4^9GZQAi&JG&=WxI#n&q%sjtQFT{=a3qTF)VZ}df8hVTz^^C+tHkLN&HfZ!=o z7a@R_cxvLK0;2DT`D#b#3R0nno;dYMVs$|W5b<_C2BT<#O)F?y%9#~s>u?mzY%O|A zfJ>(f7|~%*d9{2*6^DsSR01S00Budm?0qAuMkD5pSfXQ=!jxick}kmxMGGWI8}oKP zScSGa(+R;#gV}P}b;zaKY5-cRY|Hwx>;l*9E1z1B2Nhzj9Vk1H~#ZEYVVb-_}IZX`3 zpZy!zstAj6Dws8Eqlh`2gj_T%h^J}alfV>~bL05r?!obmLz^cKE_^gy1aya>z=Om0 zcLydnf#;c#t&jxCbL7EyJCUEG6?LTk!P#MNAHRB|Pj(T)1|GM0m|ZS(zr!QMTa^V% zuJ>Y>wO|W9B8krmy`MfDEliEnP)*qS$R~L-2b@WK=jag^cI6(|L zxmwR2jpFga`4bz<+7ZfQ%Jne$C4CUwfw5&yPQAuPNno<6k0n1G*^y%paRKl^d`SJ~ z`XA5%VHQi$z<_kF=uvs*pDY^IQ)NBHne#$eaFxpk$_LBOD@XN+gbZRbo@UMloZ5x% zZns?x!4t6s2`l$c{P6iufjL#3HDPne?l zSzZo}CKWeI#Ho`2ZI%lk3}qelbdCjT=iq~-P*?sFx`pIi2L(<$^eoCxmbIO&5D)rJ zOtSD;IlF`#t$KuOTi)|QgD^e<3?o1o{|t{iJh?re@42UPMde2LTx@Z;8FDu#g~W+% zQOL>o+ajo+1MG5wTm|srdz?>_wVI$< z3ouv>_yxQa%*Np(W?4zcJSk?>E8|JsRtc-}#fx8g@cqIB6a%myCi(CIOAQ$OinZ~H zY~I*>X6iz~DLVBMI+HnaRA4cQ7lH6v1Dt4hJ**%R8e!f_ zp=fx1`pN1Vh+E-3D``hhguDdxELi9x!u+Q(a40P}WA=_v;LYCwvXu=>E?yZF3!_u- z*Wjn=KEq={o-*GgH-?D&#NyTtwjR=Yjz#0u>(;C_B`b>0odo$44it_pEzI-HsW80? z_t7vf2@DqsmtVRieQTVsZ^SdS?^@OGRF70o$#t%+s$HhYV&mq zN2)#2AwCOSa|s;!m6nR@fM*hn%R?oaiEmnd$kFcKqX8ov&_GPZjHluxb-GHf%K#Di zu?qCDBu`)JeWZ`XBw8S51y zOS+&_(9VWQa_n-lE)R`aLuQAlY16CMaqI+5aKI*t?tfJIY2{>fNA(%@u`w|wRVqp5 zL>p*N_A4Int*YP^38SDP!Og59Qq==nY2PY50Y^wF-JE=oMT3r1wsaSRM&OUiq9cPL z_eE|gtwg&Odf^^9H|7*aeRp&yR=gzKuJ>D>Y{iJepia1C0<$Q^h^J%8ism;79HYMq z@x(`w_gU#h3-bbVLItfl6xeUeg%8yt^DMbZ`uWV8vzl>G+GHRHq^sdsoOaEH_MP)_h#_H~@ zL6ILSaolYf9uF*&#n^NJAO!Z>sXw$*Rp4UC$Ck3)RvyvzIvu~qQR?;TyP^>dh@mmI z7H;Q=Yc_1ToUn#1N~Erx3Ya&aa4t~bnUM$**^+dulZF7xNIp`tKvCetLCC{2mw!y= zY_zp_E)vH*WOWkSB(b7EPy&L26zqjLc&HG+>!5RwFzai^$!Z{ zwXPlY6$Vo&G=&4|&Vs52;hiNf!S(9~^OGR$jV)8oJ37V|#Rx@_XkT~<%FR2P z{|09BLl&;&Q?Y1m&ffWS8Fe1FKv`Y!nxeJz<|!8~BqxrzAUeCM+@^0<=WpM7vrH zsVKBqkJ>LAe;mhJ(S^2X`<{O^M1`<=I1zvmC1rDV)bKLmF{K@i*LN$ovnPfeA%_HF z9jrm`&ABHzC%j8sN!`Dy7UzQ1rdt=`$XLQ3fppCf>b`{bf>+u^^n(;dkkdK+64!2I_mc$inE ztZ|-Z5CLs$1;e=MOAl=Yx^1o4aP+VfYa-|j)&|qE2ug8sLOZ-T- z=vw15Eh3LS#)P=Pp2+-0HZ|$MkRxVqeR6gV!@`I> zD0G>1yd)M1<59+S$le2NI7NYU*cQEzuzjob?W{gFaZpW`W#^PCAE@oJ@Wi^AlDWQM z0DRJt2zW=U8aDmmCk1>`!2ywyN90&D^C*9;Vi^mbLT=@pnOnxt*SjWD%!^N^fY5<= zfm*^#@Q7}uk;!s<`(Py|C&Gs0y*T@_U$k3A&?ZBxu#3EZY!_WJ9r8W5#}pjm`3b4? z2;3cLJ1KD{<O$p`)K=j08BXc1QpCu zbF`c_=?~$aTw$CxZ*Cs&yyb@=N4>Fa;M-&?6h>$|CG8uCbUGhnK56h!5!-@2i9kFp z8;a7tC)VK~aLwMzaiDxzQ$!0UqS?x0CPUM^eXgzw5aqZ#nS9w?k`*2NS3E#%+L?`O zcW!ya<5`Iz4{U1!C5BoIQFi99Of@Y(hm_6$iQg%C_Z%f42(f1==z`}>zfqjmH%!or zoAaYm?SiE=g7oVVkHnZ|2*Ls5Xa)ML@XmUht>$^n3%hzi>)|ho5VP`Hle3`k1|!~q zW*g?GAvG;Q5?ZjF{5Qv)BTk7|V3pZ#q8aB(BaYB>XXUw$qMuC_ttq-HTVjY#0>Nqb zcNYZWdJDTQ1D^Zgadg+O>qmC?lNpy^$a$h3#NldUxsyYaLOX_o%)=VZ*EQcoJ4o9_ ztq-^Eq%EWpuX$wL*cD`x9P_mxQ;EHMnenU@6-p~FD@>;<#VfsIsy%=-q~aD{wDf#1 z7qBnYq7LQm7L+@H`Hc+)CvU39n)^*-o2L&MGGaM<`a_nUPwO9kHko(5)XMI5lwH!e z`EDN>4ycx{GhE5sfnY6&r~=d%P9azzyS7lY!l5g?e6MpcSZC~$ zQBeCs90r+VEdS!n)v7F)IHnkGOg?^O-*%(a{2`>QmK>M_Lxw2Dlhc#{-{Gl#RV0Nh z`T~;q{>BM^N4Qg)^STyo$Un?3;}g2ODT|pS7eQgENzL7{7zx(4$%!rSZp5UJ^tiP9 zVd5-V>`AQylc)$~&OG@qH2i~SZ%Lu!G>F1XPO(B*;B zg3}mgLD--Pp-fQQb>RiJNeL_RP9lf`Cnuyg6TE=S*@~&O6fS4InSoGuQRG}szR2=# zU=jr$Nhr%(*+C>NrR-!?#r_)^E^-8n3XK5Wpaz9;%GAjGWF4?gR(HqPk{#x4bjFV) zIIO5e3J1aKEBX>0hKIyusw?j2@&g&rcC#p)JtWPCsSXtUPX4wAv@1I|g%)Rq#>Qk) z(yWuEA;6eAS%>O=YKhVzxLL8?qb8lH^jUj|_0ILKvL2Y-uaOc5lixcL%3MG1+{?iRXJ})Z8in{fw=U zmb~J-R;|Q_@I5Vaz1z1;23hYsq&KWmBrS>nD=-a;#n*CXP}ig?BZ#D#nR~t%G_|QM z`>h`a1VFLJ&v5YgwGxVC5q3&SoD*zmsD*|GV=1AN^-}=Ial=9Z&s#EYru@M&*}|av zBbJIsENN3Wk>aeL+s(JUB{7NaHs#Zidh>7`!+LR91^Oc%}`M)=u1U;H(JBj;9fmv7;>0O@# z@JBG#DrE|0T{@&t07186{GO9O5g z!H9LPEbe}5JyNc0Dje9e{zQrJwM64&fx4ofFp2|VN7l%A!SN27f&ji~`8mS+sG>;0 zn;@2Oi5NemJ4AA?S%i05@M@l-XmxOb1&SKudeEw94asr%1r=-XLs(O3s8q~RP>kbm z_l>qg0|CN%bMqZOXqv|Ym{!f6ul!K?F)w<&;p?q4J?^0{;h%mL}S z6)lx>-#3#xTp*5k_L1AX!`if-UYb+C<_*67;PB+Ygq?LLb6TS;VAKoReljwMyptT5 zWG~u!UlBira}~Hl1OWwO2m%ghhuaOikoQiXY7D1Y^!ct1bnDTTrmPP!~?z>v1tJ-0Ds68FS)|4=dqE#EbwjIc= zejfse|8$TgVJsN~CiHo2F|%QCm}6&*k*@uvyDQ{ku~Rb>Y96Ef&C_U&eEym(>$k1D zsej9kP5n2mTfbx1rkl2H-?rYHx8-A^fy@|1ryf|+am{U%Pbp@W(sH?NiyC-QwmKfD zhn)Sq#JZB=^I;H4hBRTY`+WI}bt5RseTlGkxx}WUHwe;E@Awt_f-F_`nB2z!Q}i??TfW9*N)KW?gNbvH9pq3t2Nqs zL+eegzi7Rs_0HB`x89dEW!So|TkoiuTkvpptS7T=9VG@iB3yS=I`~Y2?p?9b7iJZP zZ&lJP?d$zu?T;5klI1zGvfivX!|k{>_;sGzTYIVaZ+!?+&zs?{+ataX^ejcmxTHmc z0jU^_Q>=(~Lf8TUSj%{4I#`uw5$)pnRhkI4`I#;5qjpmVrcM7oS6k3z0Wb5&A7-o5 z3ETwX>)6l+DuiX5OWU!JMejtMQ0!qE@9`IBzdBpgBIk;F%h>41&>;|EG9|*W=M>EU zEuiYD=rW+WExAJK^4vm_Yej4}h5u%*RUZTWJ%NM+Apdw7o{^*jHVx6Qeb-aM6e0P! zK850-9~c^G7d;UxQz$F!D!s0mUD4ZHeR%C){oD2bXL#tj`h+-I%+$BpkBM@s})YGiOoI?fi3x)YOwo)}5NC#`e>JlX*Dq0pUJ z4N}`z&(hq4kh9GcT0A4b^-+aZE0x|>yC=K2J-;%o&EVHDubRkgD@j~<-mWImfLK-P zOB77J!pMPwW13fkbyG}b-N?{5O2jlO^nmp@-zUe5Ly8nIQ@Gctyov5@58_E(xXgaV zn%gXjJQo(lmg)kPKZvG3@q6 zg+p{^g~CMnl&?!1t#jvqMVnRM28^uR2vcn5*s95e7NmAb?KiA96Y5vHmmZDs*=*$O zD$2cd=7A;({DQe;=GN(Cmg|q^H#$w0*LEGJ?o_KvrH&RE*`gwb7=H;6s)QI;6h4%`I_QJ&}aPy)W-DI{8J$<Fdg-U|WK0M?Y%#jAI| zvepuN3)9B7BH%$23LnNQG`x3~KUMxr`LkuxKw$u)bukLPwH0q-fY;&aO-@I0`OGSy z@&LVfP~e70ke}UlSsNKZd<1osR5J#FNjm*7xzQ;HQn(Y|8i%r_qvUdDMbep?mmGO+ z?n26!*Ih@i0=x{82x?d{!0^NEHa6o_c>k4Y8nuJAQM;nnOIDay+x!FP4~BH6U^j&QODm;x)} zln5*r@711yZlI4ZVn*B@LK9gn{d(!e?hkQmjh6EWh&<-yg8;YmGE~FRzTA}xVNA~C zT-iUEg`S>}i`P*!d{=Kz@440A%$5!lFLyUjiv{+@l~x;CWf{fbA2lLceXQo&9p3N( zC7w)}R)q&F{nK+EwmeUwU#b48?-_UMRwpnw_|8emTXudsi&%SNZ4Ds}oaX?j>F>6qQ_oX?3PP;LYILSw=T5M6uf0!Q*z|2Rn_ISnq4|Y zB1Ngck{1^u@dOQEs1Bf7J|s<1_cA%r$=jzH=$S)`-wUo1a|rW}&IQw?E7)QqiF==Z z+`Nf$rglq|ydk zN&1W9isSVUtldo8Y*y%nlKMsgcen=|e2xq0?4wTXt}!_p9p#C7&41qEFzXtFW+H^4 zZ%m*W&X+UV(n)?5opmCzOu~OA)vJ_xjv{g^sT2g>i>ku^J}ejZ4E4Nm5md`v3GMua z^7ASiDw~+kaiZ^8bs1&fD*C=r@xpZge6e=ewp3u%{?v$sHz-wVy^l-~@rD#Xzg~k<-~{S5JxZ(em-uDVwQVCXpGrknmt&(tm73u8YDB)i92Py{6AWh}MxQ7%~c< z9{#`1rSBY34@IaW9O&IS5;Wr4H%A_<;>vU``@;iEk7n}|nF-QdI5rU(<9(4A z#uB2lkRbsY{`^Sd>c$Z#IGGq7Iv>w68J`>$UIaUM34Tv}Ry%~;`Bx{Xlad=PaEJv) z8S~}#>@(%dB9WEbg#BbC#8)qCRI&}uLWX|!uhJn3Ekqg|gG`OiC92*_S!?P)(T4TV zd%_uvHa`%@I!ZEvLh?M)31bJy+zO#IJxl0ocV0i*h&Jx$Cy?P;_h6vk!Etx7ydisapKVp7=BlwFi_2krEZ z(?vWAV*L6nZkao5i9RsdDQhbwwF@I$3R$XRW>&W|N}Y$l^NyZ(X4POGA+F5H+31L<>Zhk zL^0nE(UXB95y#+;Q0X6f7ww9zt=)O#cg;$HrK&-1hd;;-c-*83BPC4xh+at$|F1VB zQzJ3%FkEa&$JJeT8tEZkNo-!x;V95&8d?x1jnd!dht)SiTMdgXWYib6Zj*Iv?q-PP$}e+zZhjVvsU89+w(cs{vzq-`?bzY^CwF)ywVe|&z2Ajn91X0 z-uA5*w?1kvUuDroZncNO1f3>8#A0orwk?9H>f&HU`Ht2v9pc=~ugK;7IxMk8O4)5-N*&}&Z7i`z7Tm^G{kVfG+n@lJAmU3; z?oA;G2a@zFj!B`XbOR)K2ujRQ5_4li#xY`V(zn-cH4S z@i10|D*h!o_T|9l>ofpL-yeXAV(yIsCLW}MSAUChAt6?9i#*kb3s;9SRPo<|8pm!4(MgWz0MwI^syTBKTEwLV z=Ot$y2BBf^b_;(VPXJPOmI*Svk|%DnXd#$xW}DMjWR>Ar$CjxWAeJx2PPds#d{eei zr6IPkj5ATsXoQ<4I56~PywEyE%ICp=`NbfLp)+mwODpt}?ECIWO zgORsgG62G1RKP{dzM|+Emp>PA|N9nb#NS?hgsSqdU zk3_}<4>}_KZ2Q|v)&v>4^UPba27rLs5kkXg?&JTih&xFz#iMi`nve6etF{qsWJ1~n zW%zL?zZ*kKo+Ll4&ibfAC5q%E1T!)BYgUQ|rF(<($oW6XmNWPQxQir-X`ym#4Hf@m zU2U5wC{U;&Y;o-t3h6P^`gh~Ky2krt2HpnmK#eaI*X>-?kp06ZYLdG^_ z@wAHfSKvqwuvzRSA}cm9y;b-cI*yp`1+_-n!+ZPzJ)6tdRNr6y&)TDFuc>{j_U-!7 z`k6+f(QNcJmNb?&9@x0B@r1?`8?SG?ulbbbP0jz)SL%DXqDy$I!rlJ{gw5VO%(kqkLFjdbl2HOWsl27d;XD9t_PJaFWp^vHYop>SB{DB zsdi!Q3R65Ox`|PHD;}SMBY`PC9Bjx?8ciQknX#cpk|bAIAIexn zaFajLQEL_Czu9qZJc*z54q~BW!{87iVWOQRmWgppTN$HQreOayoxc?>zYOox0c>z8 zx7B#WNxHj8a58*_Z-T8@0SS^E${^wl-Y;=A`-#-Igv$m4JUngn(vHfp+RtnA_2<`L zTz_TbXJ%|j5Zp8y=t4)oIW{fe+ER!g5+hjK+66A8byilF=%Q>$HWA!kUA-p^r>Umx8)|c)QnLdM3lD&Ewe?64f(j&g4i>(C+3{hiID;!{tq(8r0d>|@3D3Z~%lFSg2IvQ+F?cEj3P zB49zrCYSHY*<}nMWd>E5Lj;Ug80^&q1kZKw$>-aV#XK2ef9C*XZ?%Uw`*8hU+*;JY zAu(f(I91GxNfo=CBm9m{w3q59HPDfXBn_tH$9AGFIE;bn)0+?Xo@&#qNl(AfP6ir- z9hHs>d!khPX6=8dMN>dDagJ%pRI;DEwy8-1Uy^9tU4fJk0*=bdvElk0(HHNBJH4NuzS?GFSN5B=(^%xO>nR}g5X6^* zi;rfRo0jjBHhI-g!oZa7S08)7qg+S@>8oK?EN>tv8s}0tCV!Hafw;MXBFKgiQ!;ut z4o>fuHsbP;N-9BIK+DY~xLJ%BzzXYpIiFVsezv`~vvvcI)=mm9dn-UgglD^6!>x-6 z8!r!cczjRiW2`;&e2g41@K29LO%`)?W~IzRxoF~usX^G>daYKs^b@uiEn z)-Rz6c;%1=uwdwO@AS8>j|Mzc@XF|y49z>UwTkeLH%htk9QAQ(9Sq0PMw#|cka=s} z@}DZDAoD&`eRQ@G1*4*HLN|E>R4+9&3p4u>A$ud8x+bqSwiK(iplLV4d&MQ8oAXVdOZcjdOliF zIX0Pj6C>jY&`1Fw80Mcr&u4l`OsrAHSRu7X4Pgw6=kNlYyknLP~#S??q+L*^k= zmEDQR#a%=FIop;k=bLCZ6dB!aes{UKxl`&lS4xL!&xb7fL(Pxa%hE+zx4u|vKC$`X z?AND?9%NF3O2h^hEg*E>#C8HbkfVQvxjdTkN|KJBPlg8Y^Rt#%A=?3h42bkau9D?q z8PpYiy%ABUg=0VVY~(73t+`aW&YlZ;F7El&o`;t1Di6_t?5*NiHkhsnBB>i#K*Oy) zojs!E*F=oV;^)-?!~wV^yUT{9_T5!+q-8Xiy)L;?Tmro-P5IQ>gSi!YW^+~_n^`kE zlLC>Yn@iJV>~5vrjPnPyUzQCU4M@(f%!~=@Z)`m8Bh9+I`w)9AKf;ED9LnkX^|um` z(XTM@bfhPRbj(x0R@c;W>TI3O>CKSg^j-;OcxbOiT+njq^NGJIUZPEqN(FuRKi|5Z z#5DeVs??MAe-R5YPSnl_86D_6(JLBx0RW|UYT5gjCY$EP3Jq!Hv~z$#*@@6{YbwK?Bfa0tn`#%YARY zgeb2_)$#+q_#F!4Y8i^!-T80Xi*=`U?<#gawR4JpGCGAywR$5kM{6rt!S~z;YqA{o zRK20W{Wq5D6oZ>CELWci*&nfgXNse7;s>^2Qp((sQDznlqcq~xbZy$T(6f;rC6gyy z>FSeVF;^WMO&5~-jW{;(IM*xkG@740Ae;xg%`W<68AI?YP5WfWYGfJsj6GG0D>f>1 zjq0CK&pBKFrB9dsJ+Pdb_I%gtW(ZxEi`(dt>%8cCje-n3_}qXy=$Fn0y5Gr~B;lQX z)ZY^>)@C%LbK%yL3k5s4S;QyIW12W^N(!SjJ6fR79=VrvI$c@nz(53^)+~@vVY=&XB-A-*dCo45 zLge!GD=>`%be|9A0Kzhz?U-*U+A+gIw~-AV5GLL~lSf0Hclnn6JoR2Onjq!=JfLHr zvwV_bP_kw_qVph;7uydy;#Xx&z%1~`68F*JYr@0Xj_R7A=1zGGDzJM^k z;w=j=FngumdS%>y8)eW7Z{ct0LCo3(Ra${3oPVNspeAMgD2Q!~7qA3Nuix3fsjlKeD!;Jxa!G&-p{JaS96l6XTBKe;`o zE5LXp8k$vlq>v84?_HY{ros&Wf_7T7?`K*tfx<*?|Gt zdGl>^AP==Dv%7^sShp?2Xnm~tm?)KB3(uwN!w;9UmF7W$p&@|7YdOk#1fdKIfN&wr zuNT(W(eGyka!;G@-+9l(sE>*%6%kCe&TqnE`dZ0hv@G_i!pUb z)nu3mYKLymS7!+BT0Vgc&kj;&p*l(MNS!F$XL}*aE2`V8JFC0Y24l1Mb5XO!IixQc z&uAav0B7-WpOcX~q-=T~EVJ(-bnZ4d`sh2)xbr$N`5}n~+;;hvvE2|38-Bq0a%1F_ zA1FMc#oVx{I;He-WyuO->Ov-^(zy=iXZ>w!yfxj`x!BvkF)A9aPMwlVhd_iG6w@DD z6t^e3IcQh!6Enc1x-?<>Tb{loyF!yNGeYgXrcRSB#(5QWO-poz)z|)6%Z~`t)UBl} zAvuGbs+w30`=U9$c6RsJ5Xc<<4KfG%mBHcE6q!HOPQ}Mogf?ncG?!J=GQYF@?(+M~ z|IoR!tfiwOfSo04bJt{%5I{jXkFQvwY{v+dr132oW%r4}iPj(bNsQRN4;-{Q|niJ#?KoF(hw$DxqY5@`bXfe0@$F%U+r-3Jd*vT0AFO<&I#s);_HXr%HXhS>Y|zIl%pF^&vZVIbDDxYi z#UY@mPehJh0I6$R@4<>52mUq9_qO_5Yg-#F%}J-o;#R+M{mrYXRiSL(*nw1$D7q07 z;t0pBD-iG<^!6?%m+dslY1ZaW=n6zCrNKttj_p5dx-RK-dg;%Z7yn{>Kr}B&g@J2S zQ6jWku&=};(n;bP4tvj$%AZ%>Y{REtT=l?+lQ)hs|B*KVrjx3|cR(d%1;a`leU(fP zP!?dRELfwo1w%jC!JL^X)OwC^&_*oLrjKYJQ_G?Qany?5_hCEOSR$izON+pT&oy9# zms!2#hp%6adQ?AdwP+f1+sM&hKG}Qin;86xtj>}MB+S&zuOzl2!!Ea#WwS*LM^`_d zs=t*alN=0;5rgjSd5Y2qZi*ZTl7yMobATB04JUsRk?nB(`7yWf*%v5c9cHb50P3C3 zjSeZ)BISGTRA-4DI7qvO7kfwMh>2`ESfF^i5&4FLKApmt_}( z{TgkimKfpX7GZL8$asXRsp{^s_vle4v99q^jQDsiR4ewKCx7OV);o9 zaBP4OZ*Ydz;|l`L%WXo-L7oLM&s^JeY<;x#SVnxWD5;xsJFj0bI(F^Ctu1_APHfz*1A;?aDM+H#rlb}5jz}#}7y-4*ED=}B4 zcF*CPybW|`fe)wSjkJ)>?_2=u-uXT(&}g=-%6Qa&XO8F$^$7WxJu&5;WiHLw6fOpP zJ+czzqPg|TqB()M_N?+erndpuD~gjkmE-EE08e3uD<`8Jra9Fz)cPK5ZnP%^3MgBN z%wZcXQWL4=YO2a+H?qekXpgK?R>~+8D-K3o<*BKy0_YaG$1`-B@7676U!7j^;hnBBAE`wG#a0N6^q=D>Im5V^+Vh|?-; zY@!Ww&a3ys>XuW&-=6q)|E)7&YX)H;3QQR2IV%YT>#cBD$ho&>ROAYha!6*6Qto_U zh)rWthyZv<>S1nUa%kCZu zukfg78leEZeymbi_kx~}(Shx%D*aOw6x8tw{OpTpiMLxpIUP~8r0`jz0&Pb59+@U_ z$<5;*qHnYckEC}1vSEf#(}<~73x zn-=AJEY>TNBFh6@VIg#|^>C7jb_KyiZh2_V2;iOLP>aq)=L_zqC|ojw%CKm`#7du+ z$+jVz7GF*qbP!1_SzFs{#pIu_y>`o%HnYJwp*vDqf?JNBZ#g4DM;R(GWHxyopJ)t4 z8Y7mi_7RGtwJolnoZg2im770DHpo5hNWW^CdaFNZeWLXrSv_*>ZtK~kZt^49$Fpz3 zg8i)Om5t9pjQ=dgBN{6TAF(#<`U$&4Dx>%v>txa2!AaPvbm1kLcc`y9t+zn2q)$IF z7Ba_fKL0*8;O-(((kqLL3MVq$3F>CA-d61r+gD+8D8#|GF%}ZK@UWNj$_IpnTsr$a zaRt8UfvQ>u5fQ;ZQf@6pQASh9h}C&D#OfkzOA)w*FY|6YKcz4PzZj1G9dZFQ zD`aC_l^9(%ZBS@V4I&e7K%O1qn<(pBDVS8kMN)+?g(Ve7lo4r zxG?`Z*y^?+45R`Qz(psQ*vzl+S4kb+4=FsO$MI4H)Orw8>hmCl)^}CkW9_yVKzi8- z5oJTE(>hTugXW5eWMr;YV%g;^9r+)mS;2^e&!9PkAnJVdI(D-8L1Zx*suc|;=6*Z7 zVC|OvtvhbovRNVMo3?Jw|5JZVC|XI~{MaTnb7jv5StoRb`WJ=N3wTnPi)d^GwxU2o z524J5hs0*cEk%qeB44bF#q@jP5K01iPrCdR@(j>B$?8HwPLPAMbZFSkd|Eb<{a*I9 z-ezT{a?)>h$ZH+25_k^n=AkT!DAF40z<#PiG|jXKKVS<0lMn~M*@3yA*#ZdONC)T? zn~MtAZ^Pkg=6=vJTHxhbubY6Ms@b#B-3d4j9t^ao%r*8eH6QZxR%Lx#`*-c!e8Wvw z-f*Sn^Yo*#Durkk^Yafh$*CyWtt+!9i0a*0OeK*$uhAG=iOtD9Xu!x&sV(-Z98c!y zxfQJq@0Apx8mC>GJuQ1i_9k>yN%W(8rd5OM!>ki!QiUd1SX#4+OO3pvs5v`S_8BB+rzC4!YksQC?kUDoz{~PhC0~z#NUBJXKTGt$R6 z8vsQ7nC3sXcIMUf{o~_qwP!o`%-_(j+yDoyb&+m7_7#shMIH?P*0!E|rQ`a=SiI4y z})WO=QkG96iB>)HOU3Z#`TS-H=faWW&`*ulAkPNgapnU^7aU=lU!xyIWZZRhpMaU@J2DA0dUACRHi}B z@}ae>_be^lRsA2j5fjaE=00_&RK|I?OMtw>YQd;xH57q{$V^5uxCr}31V^S*m7BId zc$JRk%9^^D*torRb}aZE=5I>vKmKANApgwm5Tp^)J4OT& z)tzIG@Fet)WMQ5l64+Sz6^bymIo%YPr(nf_Q5XUBq*M$~pp*fbAu5WtTd3Ea{w4dH z3TY0&=*}n}etm6S@Lx>yO4N5H+}I=y)kzdMO@5MtQXOx zt1kQ*ch&E$|2Jd{vVE9lL)|nm;L;Z}4^u*9Fb)$%T1e-I!Ai|EE~IbcNNAf8$(A2T z;4E*Ep`AvxapF=}H8%6#0nDC%RWJ^C0T@$-FykXrpfUOTI)y3T#ixR;En?cDYM!O5 zsrA}@hlw%nojouNxB50^hV+Gv8yX{x{h{SuuCW!Iu0vcT%>^Y^~>8)u+`y-1vjW^BXT{yijpiVeL?s)?A$LAKK;F%1LyliF60Fj9T?* zzxmV!-zGQH`~<16T!XGSku^JxQ$spfNC`y5VdPI#79SwBq*3>#dSb^>lewSxinQ3T zu+x+$MKt(I>csQ*(mPd~lQzaxTv?Ufq@zZ&`TvIJ_<-Pu(TMckdyjIzxsehqt3Nwu35|~7E9}qSAN5j?6|FkFQ3GGv+ zWHAo1{+g+Uet*P(>Qz6^@;hr zSX)_U1umLM)1b7C#({mb)T%mF=Q&hVCY1YxzW%;7$@*whcJmU^Z1A)zZGk-%xrum+ z_{p(LJ^M0zt{Tz?~wnDTQEM);>2#> zvKm1FPfmz#I3L=H^5ZbYGtM>!LLhhBXn-JejuB%tPFNcbhVVdWL-DZ(V3FlGa)*Lc zYI!XrhCYWM=i$x?aidyK+*|cqlJwAQ5~4gurE6@pNi1N8#t~n%%2sG#Z4uL0p>sdO z`wtBS)0gLDBl25wnZjQtes_{l;vnp1-f?`)s|oK`dPVNXGq~djl^9X=!MF_Mm5T2Y(t z^fj`uC@_NfK&OlC{AKnQ(}uq+ZuTkNg@JJie{GEr4%-$}007ZQ{u_TtzuYARLm}9j zR+7#F<_FnDLoN|av3$%tX9eu38(2pE%)8fht@4`nhQs zMMDdJ>zU7cno?vz;;h>Izs)x^zu3B=^}*JM$-d2|YBGHd^&;AVI-pTSz(=17wsoiI z*f`Ns{Vy@cP#S2p2@qgF*AOLubeE1C8lmcg-J&D|e?0f&>^wXcgtc1%d;jHN0b0nV zKFM}n+~nZmj+@sft7+jM#RDVaxA0p0eO$Z0zgLMa%SRB%<{O_)MVWw)3JN2eu|tSr z@UsXJJs!5FnwSpfj$foMUuEkvIg@(IYdzIDYY$Uhs$W#!>lt+mu?6&)tC?jnYNn{D zj8q*=o^Mz;#zf73fr*U}Ig3^y4F6MEV<_qXecU#Bq7o~zpVGLq@#)snAiF@{!`(>6 z#%4mhDVug7Q8WCsA=*-CBmKZ;GBGTL^5duXDwuNs+;S*J%-Ik~xfxxrzNq$^`qlM2 z>UY)utN!1O_t`)-P)7bZ zTN6ORNjqmMQjY7U_viZvCtJ*cWK2_f{rKVRvNk|sE0LbTVD&N%D}mFjVlh+_HbC(z zdNaEQLA&b53VG%@HWFCjq@$|j3NkX3N}%>qtFux!#w`=l5CYw zc^vv!j$MIAms}|I92Ubje!E;G?-FZ?>NxHnH5G)u_PaBoEERv^t>tv;s6J1O=n+ za%?@T#ad3xiXapXG4WmdaSa^SI&+PeKb-d8{T;rWbYQ~GXb$gp^a*=yp zmOaS#ga|jaDxt~6}Rby+mo5T@FuqMU#8C?u1*TXM`O{ufUkzhmC8`G6R30I z=yari5vD-%L=ZlO_@3$CHn92eSNiNa0tz>b7F!Tawn79&wPCA09|I5l`oniKa?SMtPB@=1)%DZG$=}N(w`PV2aXKmK-i< z^rqGus19NSCrf^2%^^H(%K@L=zGffYxVheLqhWDWR~wCGqlwI4;yyjVF1|b|2l^BG~`rvbjUtXPE+jG3~F#NiE(WgJD zoWZ9HO}f8&$VDd|ooe&gm_0gu=~cNQ;gDI!&u)ko8C~wfhm%NY7rXQFUO3ZkZ@z{) zVcFXGbW4sD-E$H81Uy_xFL<1;t%;7mG0TnhTh@2q?Ny0{nhG2)gVpkNF&uwp5F%wW0C?oseV24@P#&d zBJ8a@Ah2-wL>vU+)jY;&tj^wuY0%t_3n)`Ub(byTjSxVGw4cPe*Cv!$Is4jW*`v57tP$x$c*Nm{nb?COCdLYyVrJiri5l|GUb%(G zI{sO9m4`2dHCy~8D$V3I|BpXi#a7J|j!0`#;p$MyI`!D}vIh}CL4G_vmpz30Hz&6I zbeNJa(FwD_KYVYtn&6-6d$3%Mw?!o7nZ@4bpMbc1hFNy}^a0LnUPV&s{qNpyn)|MQ zc-XRWM!U?2SfE{&7q3&|;pSPe2mzGkAf5WLVT9y7JZZiS3n`*J8<|;KGu((Z<0vsc zKkk@gpnMzd>B@FV52GUL}I9yT^RNTu7E2aZMm_Ihe zL-?7&%gn`V*+r!Afl=TiOr{PtsQ;Mqzz*V*$pa12d6~@QHgp)M&8lKy?Y4XL!fdtbFIlqa?_-)<**QG&_`_r&IFX}* zdi^bsFJ(y;iBjQ4E^0dL?2||M;Bn{2iWo}HMJdc~9p^>m6qe;Z|I+gnu|tQV$_*-f z8lP{y5G|z>f-;=W`{Q!%rUx}XG|j>-)xqskjx7ajM{zmnk5oY}fz1)uvIN6nmt6(T zHy8Q|OALdYkdkXmH)a~Mjf1}66*83i=&)O#Z_hLTZQFopB8bLQ!m4+|x5KPgb?CsL zv3zqkI0+I_)xeLuKw%W2H+D@rQRYdYl{PKMtabG7xvR2XBP7U_UZB)uE||AZY#X^n z_97WPzEbHAUIwcn!GWackq`9gW=0(FLRe}lK=|$hpfx@sOrZ||e+^bu)>A(1?c?Yo z7+I{{oZD8M=GY3 z3!4<1G0GHGJ?qY*ZRaGlcW@p}qu?~HmDG`F4LymPB+>WhQ*olfSthU%PNDIJOEJap z6Z7(H{<_rq`_@0%vhRK&qTr_ZTt$62~i9SqiAkO{VBxBG*#MX#LT`nIeA1ptw{Aw4~Ip54i z!ChR2Q$_d`zfeG=@PJxRYCYNZc9>gjFA906fJ2Cy+Enrfb@0|sPD61b)@?{keYko) z+4ET{{uCx;+XlrCPGZg2)p$?sD>eAUw0p<)?8VmM9L~SQ3m9G3;z4Qw?;kq><@8hd zb)Wdnq`(U>jpcOn7`l0dL7*K5u1+sn^8eAun7{;$jFSgS$ap6?f=H^}_fac#AJ##G zZU<(E#Bwt_>y3s0st*mD*poNi_rYwrk|u1cu08j9eunZ?!3nGhX(Wrj8G*FMrW^-U zYy@9ASgrA&Iw(T)4RBi%8gfWU|KvrA6rsp1pGd3gpORsoyhiD|>Oa$H>a*3mRQLm% z^%sF_&L$L;r>pVe=K0yGw3+k4=Jq{Wt1oO2fgSZi*#A0;pxb&xM>qRg5A|-UezZ1? z5FlN3*^OYz&7iK&o%;)nVr+%AK@7()0=Nr#;;2tZp>O6;_WFBlbFUf0oE)OOBk$lq zl07>&_M=BV(m%Xk9W&TNx0013-@bVf)wC?-%_dP$(Xs02ucw>={=EWqu{G;&ZLV`L zEY;lU;MaHet?S$901I_>s%(o5TKW6RJt0+5{LzvKIz!^ObVQ8enA1P?HV@KP7qYxk zV<&OYnSu87(j-R5Ni>?$IZO^-Ar?9xZ>uYmLf@5rkFvtruBs-1Psq?xRUCfbf%;2r zM@Vb(25VUDm7n@oRdGfQUM$cDM0!NWtI1Fj+^8T7Yi8~!;8%9SBpG*kMgpp@Hhhd zjfIwowA{um+J@xvHC6BvEQ#=E=pK(Kx=)vZ_7r4rk17&V9lt65#v`uD&Vwt^$63C1 zSS{o@Ea;8JnTa{$yyl$Fyc!)*9aqTBqP3@1ePjJ+4M;Eod9IwDW^tPh8pjH4270=& zVB$8X_Tsj_>HRYiL2KKgi$P7{Ed-M>{;mUH3^v+)yPFdg2<`na?sBTD0z%vh<|g=pjlk$Q1J zynVs6sUl(z^Tn}<>}+rC^R=(if{;=@$6R?geeRd0kh%+uti9KoRm^G#$Fd{rI)l-R zn{xmw%RaKYP4cA!>N97rOMiay=hVjma8o^{{(Y*FT^M!|)xIOdqwSgTpJMr)kq2~| zk_$1Jq|km$I_9k08hAmi37uW54x-rN_}h?yv4NoZ_EE+pnWzuv6iE+@@vayVK}#9< zn~5Mp&1yC=mJ!Z*83lIm$)z$$1@G6~l|G6@^84|8QUfAZ;ol*`gjQ7h?8KF7xhD$; z2u#|$C3D^_MHSes);F<;BU4dS;$Aq7Buu!ESUhmu&EWBL1Yw2Z|T$L$%mr~3oG2%1w4 zfu&MzK(W^oL;KNm?NMc3vEzZbL3g8S5p{?*AR2k2pj;(hLR_jGHcxta}A8anN+kxYsKgB6?*qM$Y z05KwgZq-Cdzjkm;0j`i+==qS`oo8g*5}^Xvn^3Nf?5;`C_De0pP_``h=O_152A&M9 zde6rceqS2^Kc=bLGgp2~`D5k(s_cN~@4}lE1Z)c^HDbsq6bwOePa2)ZC{xywU~7_8 zyd~oQnpoWARWmo!0!d1VFXWs`Yg*FOvXwe91bG#HCdy6r-MCV;aUy~BDdZDi$x&b= z@pXg>seGyO)%?C-DDi!E-~s_xd7xmnk5Wd3Zr+OCG$A5Tj4rgB-1`UDDv@0PxiLJ?O-sK#$P*7ce!EC-MTSl_qMHJf9 zUK}vo%L?$0jTN>q#!8<9$efB?#j9^qoM^4apq&}rdZV{F)a^h}%#i7u)viTlb%WGhCBZ088R?d}MQODcZSFn5f=5x+3T`7WOOMroujxUMIdYd)Hgjw zOi15&{O!;_&Q5FxLp3(x5@{YtAXMi6H6tTaNEzTAsjLqY&#|COyNv;HxRb*BsAs6O; z)k73YU0L$TyYO7{E+Xm8p<*d34&CZZ{=|0~`WJrIB9}kz!_K;3Gz+7ywW(Gf-eG!G z@JB5EF3UdIb9K*_(!TPkN~Kb*)T$q??XOKNY-L^lRT!O*)Q`jEEGFj%0KgW5^OnYo zl@T{gp9=NC;ZSy3qk&9d0Z>}JyV3LQ^0}1@Dvzt&Sf8lh*7$k@9ss_O!^`0Z$+nwx z7j_M|Rw~2QbE}W3j#TNXsYxI`G6797YDC-c#K$dXf?GgEdKgFJo%qlT!m#25A3)D; zC2$(&LV}Ggap7*<%IOG8uKsh110=h9q2*loS!3q*h ztB9Raz*$ERZeKrO^Jxoow*t-QynEaT`GFKWNja5f2x6tV>8;&byQB6!7|V4qh}d;p ze+<{#oOqJ_s8Y;EpU^XJQL0Ai{sM_}bWgT|QAMh#vpO?)sAS*xUfVY;()_b2+b6uT zEhI_xNcEJyrQOk>)9h|pG4Dzsr#bL^TJR)@*vywCfkDX4oBQSVJ5ogt%GD4jk%x$( zQn}o2%~F}dZuk7k6RZu|_!F*FhaYn-;i&J0r;KBGa72&>CKbq>s=*B1vfDwK%G23g zKuP!VS1`di$QMC_hpRw7lq_u}nA}p&yL&%xQJCW4iuD*B%@NJRP9)PM3Ikwj-xah3 zkN{>gl1ULWVhY|b&cp%TYU?oOM&DHJRsS^tJ-sV?sn^wChQ=p#pcqvQ2ITgEoER@+ z##j!B!R5yLv?-OsZV}2Z%$#vrzqBb1Pu{13iK#p|P3r@;3FDU^77d$GT?zwXuFUMs zu@NecPLR@sGYzYSy^j~$W=2dIk-{+|V`BGNE_v_=Ph)bL2!IVn1v#lLi$^9@g`fNg z>~&$cTow{+k_NR#^mpq1F4O4rlIS5lh%RAp=&(>2KHU+FnExKe_)H${*N!;(&2*N8 z4#1^QASNv3BSeJ2FguQ(`|LXPpn`*Y!Av|S~#y%tOaRO;?D z<_-QD6v_BzRUdU2NK44~Zyu#@hGL+M=IHy;RS2&=!@@L9lD1WhhZ~4pRuav)9{tR${}T9c9rna2a|ewU}+Vb=kg!FNLKufqum!nfrtf zqsmA4SVijtj!(FerZX-o)t7!AQ1axiF_p!*ObcnfnxN<~y*Lt;iB<=wFWY}7qC*A} z!M8v457Bp7Kb*Oc4m;S!Wd8~ag3+CMGbC4|yr0n2fkPhj%%;illvki6MVQM}Psn`r zg40%Pdtt>QFQA=6^%lk9(I-caSd->;aym4{OC?TvD?h5PsqV-ch*f7#Ej6;gFVEV{ z33J7fv9OxPZImVe6I-6~nn$0vk`Q5kcfWxt`X@hIH344dB|R6GUsFEXSl&3V@$lx$ zo3CiTr}Y6P^ID(KMi-J}=j5d0aQGDGk4_HFnv7V_?LSBfQD7MudWnLNu}H_-njAXR zk_JSIwg9}>aySOZ$s;J--hG$-B1i*6K$S19Zm`@tix-!DVESWL7}fy&Ys>a^ z+J&c|6vtPStg7M^f5JIhAwXfD1WzDBLnw3ajHgMr-xoE0WF zjl|nMI$MWqTJ&;#?}$Fg@9OP&sql706Cw+SM>Pg&%AbFS*LIOdd>>3ad7({HRFcb* z(cM7!>=3%d#HS1Z6?23=A!C$p#5IQ>lG7YLv%SwX<*GXt1$w-)F%@ivFm1{daq5(c?T4V8qXBw*Z~5)z_m%(F z!;DfAy<+ZCJhy48vhv8f>ZVDCSf2O{Qt&1CNLRDI9O{pjE1)M%z^pl>IFgwXJqaU% z1$i9Xr?;y3RSaIIUJ^Jc5dygvhc{Ye3lLO|80R^VWbSj1%lCOL`f z37TwwqNB}cf1=2ZMC+qAY!VdIC=z@`!fk?PHH=A~Jil5UG5m-Ql%)_G{e&XQ|$i*&hCa&*=>&+gTJ*@KkAtS=kR!GgB zwcq?a7q(ILU_(=mqoQi*sPIPUNLB!Mjfiu;p;0E_UC)7Hb%NcW|H{;y{8v{_orWjlj#(@LtZgi`EE5z)%s`Y|J`O| znj_}IVLOY`nW4cXxhikB+J)aWwx%(a3K_iL8h_J(zj;Q~=K6OroBtYr-MwIH=o%WQ7H$uJLK7;#aOXc5-nCeNKGTt7w9vLZ-qC4=FYMM`4IKi z?%!e39cGy>yH(C>O3c=ORR38zn1tno)8nW@LLt*>HfhQl!S3H74>MEx2=Lvna*#lU zEHr3-nJo)pnU}xwAQp7l@FcWJAU9KZnF-wMqmfXK5}f6gDKL$7y?MBBp?wm`i8G1Y z0KbuS7~1QO^4cq~fz_4uO{ZX4`PT9)Ko#$=zFK8%)qksgt@;hoSrA%ND<+-UsMbj^ zQ=Rfl-4O43VJ{3_JH90<_qIzSi}d&OrQo#KjcsCoJ_=%gS+wMA0wx*pX{ra`I>p8B$S@xZMjk<6KCu>l_rO<_ZCD9;?bBd<9yym_;>6#L- zM!AjEPJ%JdNCfjH2FCWM!KzEwGRZlIoTQetyH5W~R^vN2tn*#H)xW5|rFsvY4HYm@ z$caWx+(iUUAfO#%2PY3aRXYJ3>J|KO?f(ycXZ;n>aoYjMb{By(RQN^nm<|Tn!+t3 zLJfS##pjWRAid3_tehYiE5aBdjS}5Z>2FIP0P(7Anc{@n8Rt29qR?>?MR%!PO9m!r zc>Q=-JlY`bvSM|JQL!DL>pVwZlFh^DqW8eaVz`_?;i@~vcKBaH9+HR^SkF;)7I5w# zlgO99rkI$u5f@0cO7V7}KN9jVD)yAROl<+UnaUFody#j`HM(Q=IYCKfc0A=;ozPdz zim<;CNzC-zPqG$(0YilyMW=p^toXGM+D}c{bKxDFPF1h%yOykb(7D}iwUZm>3bqFU zvbQA|865$%Td^aNRR72JR(JByJ2iVU{Z7sIYyLJ3>XmA%O6WHZVe9p+_q0u@0hU}~ zB;4NNSxil9T^R6Lpta-{rU&zMPC9XkU)uVABFE_H+VNLg^?28h18eNCiLr1bs+>oP z;-wC{X`Z4SCa}ZtuYHDJt>WXPBI}VH0hWC`FPKcap#@eE%3x zZ_l?%eT~;Ek~uk}mdXm8Y62*Nq#cxYro$(sM?%bT4DE1m%gHOT%EmWF!tUTm>L@AD z7MW!oOlD{%G4N`7I3upoOZcp_uP(!=wriqo5~mFs&&nPfuJTVN@{TJfVSI#NU>d#` zNl-ejYIdXNEHBo%TJZQI&+(9wGIHFHlXmp(SmpqcbplPGxmx7g9;v-_4P1aW8*ftf z{H9?Ot4ci6?U+i<5mO1~jhv8QkIDM@uzck(`3&Gr5z=4;(Dd-!`poR^twb#(P&-Lb zv@QDST6t*yBqS)ted{l<6}6WzIvlvnwJ2Ij(ApjHnn*%+=4lYN{M~8Vmtov)WQD>u z_Erv31`J%MWa5HChkh)}J%2kX{8X(e^a4tQXVLjwu2=#Mpw5Y1=YIhrAvH7Bv8=me z`-6Jt%M{|-coi#SgjYH|b%qzn!7wBuyP$1wd$xkaRR566K?3{}hstG$Mk2co#k1F& zy)b)i_P*3`M15NFZ)E=O`?kMPu8_)!`*Yw2C-`>n2d3_z3R6*!2n2m5_My&|owqi- z+{p*qPOv}K7FpVg%^RD~wA$J}arV`6FuG&D>y-419Uw*G7#!{*c4oL}j+JK@^=#|; zkH{Gk7qhgo!$i(f4re$&@GCmVr-k}#-Z~=G2g&UjwP(*Y+u^&j2c!ZJ!J zbe`8zpsCuE#D~(3k>UGGbLrp_n z9q!4a`uE|>2qQq|$&TM zje%KJFf!7%;`7GLA@7M{r4(57V;@(MWZUV9-xb$yF*-c>;7xT`Z?JYgqb@_n!h>zy5 zmvYaSdhYG{G6g-_YvC3aMIZcCx%otZ8wBp+yf~1>tMCnVk_o}*)|_pKH_0~` zLWEj{MrVvj++90n>gk9yX@~tK#MZ8y7(um+Tn|*)ZUM>41`l4lb4#4~_xs2sADMSi zEWi{Wp39afc9}bwo>ca9@$|vNN8tr1^ zK4G1%F8KBGwDGn9J(eC06iMW)8T#&{Pw}*;ENFh}G3u2CRk(ec9C+oq=6o$N`llpe4hAcuje5TwY$( znFpV&Kd14H#&^}=XN(3ZA$zoupq0c6um7;|q^#-ipJJ(!57p8)t9MlYtol#Yd+P7c z`arVfYK!;Z_lazEClkN`9$L^@G6-NP034K6)4`IMObyIQ#eqy#KQgDw^&vb6;b(5U zF5x%#?6c}~wYpETNW|&Mug^?k6?2WfvIQR`6n?@ZF0qS=aVQB)V)sa-xg& zHirHvFW`DPv;nXr6ls17C*zw$0~0;q0J4uD2tdFTewEb@Md7&-jB>Ue4~v!7!ps4~ z)R^<*t;2onw^D@HJ0(!%aRQ0(E*YNO5A4TKCf$5^zfZVp@$yrD>NUigmB)T+K_P3h zF{KN&K$O8R4Ph*RJ-`f}bLQpV4eI0#c!7J>JgbQ6O{A9!!NdNsI&%Qc&lh{Ralaona5&qrFYn{G|2u#y=#}7 zcjoWvZB<&$7G$$2h}cot!;}FOG`0SQo!htV(!`!VClyU~utsRUFY!>fBbE37HMGjT6s+})&1^?ybwu;<_gwteNhc?imp7Nrt4>6- z@}A14tM9FTy79Wc2lidq_iKHR>wCPlk(8K9osf*9V<1Bi+wXADUi%x%So3$}Eonc% z;SBsF=ySAD=KsOQr)mpwV{ubt@VIz_91i1fO~U4+*o+?Ojnn_9o}dB^panU_SIgxr zrtJ9Xbiz?^g*(Fc^b!?#DQ&1^`gUcU-BLtfLC*PNgiA-LAqA2+lg=sFSn@en7gHf) z$X-n3wW?>|r8!+U8I8aFf>F=k1`J>+LW=|2CP%+&`Q658JylZ$f8T1}6XJk#*1h-d z5hinoIvFqxC*hGY!LIaq5DAjb~f#m(-fRK4mzpI zi%kr}m0}1U5e|jrid!Yn(avxG4SUInEX+ci^j=}w@^^1_LA6<@8SN>;u@M3Zt3v9! zx4xn^)gr#d7Z(i?e4uk1yk_xhdV#xxOLuGnmMMmO>O$JqM+dhQqPe1SC8Sv61e`VO zBAX*~Kq8N^B1C5UA z+1jD85rLrmVG2g>1Qi?>SgHEk^{;!A>Bxs-H)e^OMYJF+yO7jWJ}4Y69m69R^wf>e z@AEqQ!?b%kb92p24@0>3yffj?&MIH!jg+reRbAyZ_@=bIikv`ru$hg~=39?G+S$Db zJ$CDA2D~I{Vk(CxpJJ3ESE*@``$iC3 zgjJl^G>uCD!BT>vmG@CN3dgD>wtb><=@v?QpV@-unD?*%V`@mv!(N-MIxrdHo21jk zo}>x17;nl}iUHczA-(hr2=X$`U*>Jy&O|dRD5LuFj|*N`%)6?93treCWDjCk+b6CS zqnYsUY@$8WSfV=Mc{rC&6bm|DlL`|Jq$lML5-cWUjnp;g{|_=TT~8^`)p_H~V9_A* z*}rq+8qFXAK-HkYL<^aU8WJ)|fV68AOAi2U!*u6n};~xvYCBjr0F`FFtif` z)b~d4Jp@VV_R`N==ctH{tR5>i|3cF65!7gVv>bmpGc+E@`2UvyDXJZe919d2=6p`# zrc{de4VV~{hsz~Y}Vf|2EjSSAu<+g>Y(FRJ*Vyf24x#R`<7 zC>&)wJBzU9U*HSa#f0b=x!gB7ifkTLv_{8r{$BtVk&1;@PcaY#0;h~}DeZtH`@v~2 z<|Vb?s6V`MS#uzImJ}UJ)UQMnA&*RwB_Id-WUy-jdTbc=fg_>P!~~g~7VyIY-wp7# zpv9(ytO~)MdXEP?iXQ2n>^j6-RJ-hW<;(!P3TA~cM(1eK%=Zy= zZcDLb2uBjT^@%rhwYFu%N9lnOrfkk*!G?K4@_}=-@Aat>jAB7_1%jwo`|6b18s&YO zgurIWMJUV(k0MxY0T6;rYaj&qcv_ZSK!|y<-piUly8k?o?BB?=ss79{Fu-TzB9NIV z0l@v9c}v$T;c4AV8J@Bjsv!Y-uO1I;rIl=f^2*nF|K$GsGIZ^^Js0#`-1DnF5AFG{ z(p}{tr3Gbud)IK1aR|pI)Y}<^rnXoM6n>7uUjYg~Vemc0Df^YUtSyUbhigZ&WqhTq zD&kgH1mPQ2meCj5QE~7QIE>8UnX)o*ylQM%JITMz{l3Ngy0Otw7%1?Iv~NEdu~tgB zjLLU)nH?=I9=pl9FP+jNQkIUw=UQLN&iVfsI}B1iR1Q z_@r@B+7V+jI2V-1gLr`zXGyxV>r5%#qCA4B&{DJ8q+N7|ZzHRl;*2w+H(lWTAle!E z6e0_Og}z(KN@QOhSt)bw&BbQ)41=(Qvk9YQA^Am-^k8oxInkTUe^a>=MRn2n6)uis zrMs)U#5ks?Px!gZr3cd}XR#~MajiT_@$%u%I&|c{Ro72unRlZHLI8w?wM|JlU1xiz z_m4(It>t<<-%|jI{L>K_+uJ7+)mMHmrIS;Ku}m1 z;>fy0&J4|QqjgX)jNW{zXfVcBiNSkeO=Khh&$CTlOokK?WvH3or=t^gkHWU^;GUSr7 zqup6OI#uFqlzV{S^&m?fQy))%!i|CQl@ZU;ym5&8&Ji~95Num&F4Z~E+>G+DYQelq zXOsky#|jkmD4lm{yn@AQVQe{Hr2O<{ispIGwK<+1|-qDM|Bor@S%RAcRk$wQzgVP4nBOB{u5N zL(&DspV~cn>XXmTDx0obt^Xt{5QN11T%iR1LbD2R?FZb5XvFU6-JEXyFoA#_*HrMD z{R7+Yuu4|X2@u7NF;E(6M-C~qyl%RZ?& zkx^7Y!X|0L(%nuy)7gq7Zi^O@2waW*;?320W^QvMN+wrdD^>hCYZQ|<;PW|w#Q0MQ z3u#1JFVG5keTaDhD~r<*x;sMQ7`56*wn8~5uL8H8{k!l^C6P0t46_!rB`m3(_toBf z*-&ZF+;*RP9T3#HIdhb}bLICbfpa_kp|1eU|B4hJ3m%g%S&22P|AeO}EORON3#0 z;8*%4`cZrS;N#f0QOu|ad;?l9S$IaY#sxZ*?@<9f51ZqA6UCq_Q*g#=QKs@ZSv%>H zB!bn8gz*9~ z6-d8zpgns0X8g|z3yrD`Y@`6abb z!X}#NbZ}D>a_z}A5E0x4mkGeh)0M~OjexF^Koec8o}*TKckR8k_toBC`#|l3wLdgg zM%F?uoBqF+2SPb|$&V*5G2bv}sQC z)c`66a|ed*48_F(3o5?W;WaBKMgWYRP{y{>F$8_7K?MpOJMRr*&u+d@mu@B0deS%v zZ6H#zm$arFAwHY^kY(%Ek;!SgX6zdmtUo8-EUT4!k%l@u*9K}+MqUWNrJkI)%o7_T z?j`ObF4OhJvxL9K^Q_An2hzYC9ip<&X2P#0<6fQb(J6@@w94Y=hLQ zrUY2nU|YGUbw}&Po`kBTqTcevUy}mcGb(=5ja|*Il5^c(r zP#)vYb@1eBLl=(*mwb7gtObPCAoFlm%Ihcz9cRGvq_vhX|Htexr?R*l{(mKWg$6Rg za$H~9R(fVWww8;I-0oOa`U6=VpR(3-@zaZR+$WuM;#xuI3l$W;o+WzrBR2GWved@+ zC|SQjd0k(8VuQL#WMFewC|{Y!m!6PaNRud@1!5TZDU~zGbYM?dotSC1AJQoYX~ldK z|I4wlbLPMy47;UvHsYUz+D0Gb&%m8Z)lXNyr(~FqgRpPJSxOb;vwis~~xkkZFdwbb5wb$7FLG$)K`a?V(s4GH~b zqmyO06GTwb`2fmcbR*VpiOW0hGAwD0yDa)b$6tgtT%RzBQr>NFO4XGUxy~Q^$ZumH2J136Z)Md^8z9JRWn=}~(T9WI zf}M@;!QWTMWr3kY&v^9p>=sUVd$6zSv_(*(2lPoOF$Ky&5bQX`HB&SlV>^QspHeB$d|KH8z!M@$o&W!yhVnRtQ%o zakHK?(hNBe-#6-ktaCJeA|A%T4pFG2#E&Z#9ZG@CqW=wFF^8$zkJKgt`&H{TZwE@w zLc`G8=Ja?<2PhPMSN7OJ()8e(4DjH{sm&(5seYH{r1hi9fRU9jr3{9vDSrRj7&B$0 z3?wb8@Uke~&8DJUP%CY3shoep&`9L(MKSKV-J#IbQ1{zWlxg7S>b1W`8lN(rO&D< zx%;acNEO^HmB&}_u5A@ROa1#onYd+6)+LgIs%Cj_z7=mD%_|#_?T8VvO>{FET-Ee2}Ztdh$;pL~L{MUZkRQ|Qh;=L^*P|9(UBq? z5Np*Mrf5tbl5eFI0eg9WdYf3N6yJNbeyjBq7e|V^kXG#Bha;9Gb|vcuJjK3K{o48v z6nj^y;WeLABVZsd-r&03aM6h+W<=2rj|-SiPL>pZ{2aGE`BHmo(PWX>J6MPBs4AK3 zB%v?9?x#(m1v-}d=$3Pzv4xiHoD>y8+LnL`)2O4>meuzZJ=EA@bgIIj)RyE^Q}Tcd zVFbu!VgQx?M=r>^=QnbmLTlLF^XQ(R1tTC0AW>;I0rL$q(ApVt+&tLWV%;RYb*naw z2h+)PcaMFsE3=+de9c4AwGo3AxZuUtHxH;(E5#vcTUFoG9B*CRy1aF;^$V?EZvATO z<*iq?Ue$Va>$R=dwO-%)t=1b_Z*2Xx7jqNIyT$9Jw0Yr0Q+OhR-P%7ko`*=vo^G6& zQtkn@B8FcU=gRC{LUeSVuUcR&wpBh5(#QFErlz+aN&oreM+pd7IvVx6++I5fRJ3T5)sW_b!{|P+9MWyk9VUzp6%``hRKWlVJUMdkdZ@{X z9#H@1QUA_^Esf(Pc?pmgpOq57@@l<7M1Z7Iy&WEbCyTuD{_vA|f1M2X8S)F8D0qYpry8@#HT3{f2>dW@7e3&%VZUr;3lBKVd{sZ2vA4C96?x)xKMMkRasm8}~K-sqsLwB8rMBqq3w6n%(zwpD35hkFDHa zyI9GC`dQ7#*p3wqvI;~aS$GhBOag-NSFL(KV^IMac>Bhk{iFL->C-e%=kWDHjLkI~ zCu)B=1XDuut?VLBaog{5H7a@2-Zs~w9!J+hJ|2L_P=}T{N1@%&kgf5_^n>~-y1Fl4 zc=gg3)%Oh@A|&tvcXz)_BEx^`M7sK?B||36J=;*GPL|_`zwWF^ zo>z5WyS{seiz00|pyS1{${M-K5>Y;Mj5dESdA)-Z`>zdgb>}t2(e|mOH)OgP8ylLg zGK>k3tG{E$48vaJW2AuyV^g66NMu#S5_*fn-B#2I4^e2rQsV+>mabAAb9_`NX`&v| z_WOg`5C?2rJZs{hrEqrGh?dx!>>98v5zs}6OA}=!JBUxDPWC`7G5ex&6w@xen#PdNIT){sK z!ITs<=nW?@?H^@I3axDXiDjSbaf=0!o(sw`GkK5NKDmEXC!C+zgbIjkGvB#3dmMlL z{~_JxIRL1-$(ZV~rsO6&068$#8k0i;Nl>0fNs8RJl+gdI?9MG<5puiJO1S<7b6)cg z7mRpSa%YW`_pv$EFE{UOk@5hGmv>uh9Sy8<6pB)aE3>C){su$hmjaND!IK9B>If2Q{=O}LN{c0X7`l#fi6iDv6XA9uZK0}t+hX|eX=%NUs?YTU}@i_ zv*`Qvhw6tDO>EUfvFbFssBvZEY6xS020!?zjb4&Hw=_0E9lNEmwb9qu-gsW)`Hi1% z?14)5o{)X?=jhO8Ouilkk4jJkVj}qxc_KrD%7$XR1mL5Hetb}($Bg%OCz(Gg{d^0O zP(IqGPBe+WR*m8XUU zX+^}NZR{8y!CtcqGGm0$FVZUbX;vV@J8kz_K^NE$m-PTIHEW0Ro`FCKd*Bf-& z9^^oqfOKH4=A~Y;TY(*}BC;TV2WNPJQ;uX}_9&7z)B|$l;aV!`^3%C-;?m&FkG)Bd z5lUXS4^8%ANmP>jthrt7PEs#53CsK;$ESE{h9?n|I z2oSvd$(QF&^Pl&5@8k{Er%$J58z})%!m}I{uF`v1AQy+*qM(H2&bFSB=4jaUbaPK1 zA_xtPgB5W1mE8xrU#`Ngpy**YE0(s-X`jPr; z*Rx%RQg$MtoFD!qZKe%EKu=*GvCMxG$y37h3n{iT2{mhK6YMwZ720 z7woJs0(pX?gX`w_E3CnLw`|*z{AwPF6qQmMSOs@x5dd)lHjK(O<*(FyE@erU0zdoY zv2{d8vJ1)I0Ey;}hsvA}&2+I?u~nz`4S7N(wEzNLRFl$+?G%M=`mylr3UqBs`$}cG zq{dE2%=C;*2^QKWRf4R^vzOs-r7{kG(i6>n$^m!eLpQl)U!3Ru(}(R^pYaHPoL%nF zX+858MwPI*1s-JK=0gWK9Xm@xh8JB!yvUL*B4@Yv9U58>ie~oi4^8sc1BYS;g8nf3 z_u`vIR1V;S>xsx_2bI&# zYqeTW?J9V`t5T4P&%xA1RJ8#02nQiBGEo!jk)R?2UaP>Gg*kVOx+Hn%p{T<3N{4Hq zh%;1qrVSDdGXJ58(`?WDNNTJK?3G0B*PRiF%!j`Cw5-Bm_wB#9U~H?k7&BrIWGlde zO={E8FHlq)Xa^MGQG=;3DXc=f4@^*{Jz6Hqya^K8p*V{4GwMUL+t=)XQPl+&jK7gzgz6ciSdR!zc{yRI1lfenIN2H9++zt`!aWteF zJDUZqmOU!y`Ac^bh9b}`A)^VH8YB#_qFlY*$@P>=CX~mAX$mIrWzl3F5~NLM%De{G zV+C~ii6f4LlXDq+Vpt6b0pnElO79Y4B)YC5BFxjX+~Dx9196~wQLqZ=46p4iKuvFp zKsGwSa%yEB19+YMogL%DxKAV}gN9v3yE098&1yHxIlCz~sU_%{(>>5Q3!?)*rvZ^{ z)J8>XBl2%t{Y*tkvQf*D-|Sqsj|XFBVwsc~(jqaaBlvWp&9hUjN@|^}3dUz@Z2F|@ zGF0@_`mGLwdv;(BsF)aDiKV3d7J#)&*rnchm%6SX)-=&M+xJZzpFkylYD1={gWM-Ut5B$_MK{DgL~{GEKje#jVoy#;#9v zeY)#!yFQ=QXCR%Hk<+?W|Go-yzVfYXK|V>~)W!A&l0V0091c{y+U>09)n3PI%`#aD z3$+DLRX_*7&Y!w+z!o{mOuKH`iL<(loVuKwm zMTSxZ$lsWw>RWn_>aqcwixhsLerIpY2b$`la@Whd@2xzs@!^Q^7aSAv63eG%T*%37 zn*mee&+VSCto7p-4s%)*-kvhT`ATyd{EJV?8JEmOkTR#UtQ7egJdJ5M^Y?a~+4&*S zk%oiPJJ>&gJy`gC?Tj1zFYCI^CZK1ah37 zNHFFPw~lwrpW%o}jfBRKysn65f43j5F0U#NRK8aEkIJ_z4^~cA&#ykMx~;Jd&=crJ z3dm9FpZ%!9LHBdz8^!Mt<;ejC(=*U+WRp0}eJr(a3Xsdc;V*|owrx%}<#<^A5ujv~ z9zIq$_1<*X`fIy6PKX=sJ!UX;>hbqQUQ4qv#x$&#`vRVbaIKw!_Mz*Ryw-2>^0!?u zeI>c5P3{adb6)Hrg2E*_`!^!-`#xLX93YAU^5e^tE?W%M;#5oc}C7h_r zKh|MumCMb()YtsPlrUdI%@U0@MjF8OQR_DAw&?BXqQYYBc3%s-Yg>K%BiRM?wmBOm zABD_RYE;yg9r=x{&f()}w$cwG_S=!?dw^c!!`Nd>7DMI&5^n6{Thv+BkwS{ z%gGK#94{LMZbOwN+!WcKuV$CC7bwYthosz5cj~aku_@l1XZTolDHmZ~`)3%UP^4cv zE}?VhDlSP0+8=YJ48hKR0z1?H{BJ)QqeJt$(!!_G?830@k&EuM>d#AQ8n7E?!p#3GIc(WHmzT zu#I!StKK`*abY0KVKz3V#urgw96S_QSZ>WB zs3Qf_k>CPU=)Am(>O~4w$?2bT#dci`)SBH01qMFI;E>QEAy{@Rx+c0_rO8i9VtK-x z-+tEo%iH@0N21aO|8kw#rU;uHv(w*XZv^+(!i3wj&u3atO^(0D$q`XYN-H0#LB}DF zE@d3OYuQt~yY!X)cvct&2n^}73c5qxlL8Tdz8D#HzJ(}4+b!2u~i!}Bo8LFP%1?aK)okP=Vv{U%QinQ>Q6Sh;!0$QcI59qEB)bjWd7vtCk#;?oA zvWMhdc{1l~jQt=-#S2!t@7CA_5jh^RmlGhiMV$mzh>lW6_mt|C1e$ zZS6m>j^RgM`y2epv+^Q88uqnrBTWsTfhe&L$EsM8bGlg-R7K4rvWFx<99u>hAPjo3 zDJQbr`>Of{7Lkk-?@vJT1TJ}c|ABt`BSt2~-6#h>p^309Z1}?KqwGg|cTxuQj4QCF znsrJf%P~jFXYaIb3$6qI zax7$E70ZqBn*~h)wl;0xvlndFG64+bpZ1Nh!ie15bL>PT&qB>F^iCAib^s%SCQNeX zj2fzWXQ7&D8Q7{*K6;(`cvx6^uS}$;rlSSDXcpDH2TklQYsRP9#z($J0KlE(KZ(oP zwET5=j{GKq0d5`|{$GB^jtJPzLlJp9$HepRDxQCZT_}Rd5g<&r2&#p%0)bAEG*+RO zHamEG>YjRv3rD)DD$AcUVgho+Z$RS*G)2Xx5c>v#$;j+N? zl>%y4vAe6kT79T?m(~0l0)nWf^Gx70m78`onMa6J&wKKzqgDc*I!cvrW09~NIUq?V zRk`3(VL;+j8i^)G7CTk4$GuYnBO@t2z_sK|Du>iDfN;IZl5a4CPkK*wGtsm%fV;A1 zW&44EtgPHnnXVl0iBQeR;5=Ir&3~RA?<1{8>$wkNSUoBhWX0vnc7&Z$mpM5^@b~W8 zxxqhK&e?lyeIw#BJl_^UpwvcXC4$P12S<&Yw^j`FJgq~6(tWJsu_}eK^N*hzDbCC!21@?Vp zE7kW=gjZT(!0XK+@{cpJxBj)}bn~DM44BAB(n%ukQ(nI#<-b-L!>ETi!2$NOn5P@g zbevAT4DOqGh*$@r5mQu{m!RO5Iq^LwWws8@;NXv*LDIPu<$GX=tmTAyr1NSE;3glq zgNES7FigCO))=oCp@3e!QhlItJ<}LJOV1c@U=0)#hCAM%6VWG91vE0N7T(?Qt9UQYbdk&2G2qMxJvys!*+?kl zNv`%E3LxAzihP!xqgUtXxL#4ThSQ5`<`#RBYy8!Wj?(P9Xfn$+*1o#XPd{p7E* z1q!DygrfR_>WeZp0~Hze#LCSmT9zWxG!n1c$@*g)P&nvGOQ_e@`0o)qjfhs#8$%hX z)Jr~@vzHz_9TpA%hz4$|q}k}E&{bf``SGpeDMXPSxsnkcqy%XKoAP6`-^$Kcjz(r!?#a+( zo^jxh%F^(}@ki{ufmIxsVIG&y$+J)M^7bE1qu;ElcvPc$PNic^iOHC$pH3%HbiY3KA^joTi3U4P)|4c5q@Z zd5bM6NaIMRushP~UInPPP3WG7Q>w2JNO7V4;T)NE__U|6UFV#!K*QH^mXS6qf9pqBNNK2eKy%Qn5)}>Z@SLxlQ_mtjW`atRTOCPi~ z*+QDKU3JMmTKNPvN@@i`ckF`R-tM#mj*Sl&6@HypCcfic+^(zuOW9-1U|?w|vz7iJ zXFJi-b^Srtr)xj&cVQPI{?(~IwqIJG{K=Bi6EHK`-l>s+Q1*J29x5t-PEF-6yYBID z5o#-43>fM92Px<^ocu8nH1rKC|B)h=uc_3698J!U^Y>Ge50pK_6#~8IByr@Ksof>I z(cJ5WZj>fwdzgzeNA*ZqSZ*5KcUM=}&&7lO4t{5VDO`IgP zs)uy^)8R)%!vC+bzh*q@vOz)i$8+a{&A7^5Fp}zEBKI+I;r>0lB=-R$=x_rodSEOE z9mosaQyp-sA=j>F-UuyA)1HwLTZ9x<^qQaLWho^VDPA`I_&*f%GGMMo@?7$fmqo@h z=W^Gvo8gt?dsy|^^NmCEA-+ko!n>A4QnYL70cZD$Z*vKFT}T;j)AT zR?(R)2+vy*6R8N|cR0x)wJXN~sPn?Le}q++M``xK4*cfVxg8milqk^cIK?tYy~8-g zL(kUc9;2a-Pdac%EPv3H9Q%<|v{LS8{#j4l%uw`2^U|5uu-4OFR9@-8QaAAha8Yw? zQ_@neyw?dQqOP^hYZZ}E9`7=g0lJ!C;D;_&L1D}q*s){NI=$1}p|Hl$QcP+hlp)*k zmzG49&|JiW0cPhwr>56@rMSmwcyZIZ=(n7RW~;)*{(wznY z9!bEkX4ydPUYg5ow?RPA$`Kw8XyJ)?mb@uBo<*_YW+n2cs5?U;m25DX`6i|_re?EJ zw1802m`b@9-a$)&iVIoeQFRQOceVbw1?UN27yLrXTWE<+FGD4cS>?99UD7kS+j8XA z&fvf8-+{8!iT6tb#3#15a3|k`0OXyv^AX=iY5erL*#(%VfxYmOi5Nw%z)}!FCyc|_ zTmS9w+yF#9%Ip{Y+&Da`1aA$y+dGx&gdOh5?5U_&r6&CpxB8Wy#$V3ttKyU@I74Y# z7p^bpPf?j_V^nC+$?q$t4d!cB65C%?x4C9Y9=63hYo+6V& zZioBkPv%To*FQ*)RgM4{E+ zP|iz$RVy(h0yYRuBb*w#?z-!KTI&d-t@{MyC^(rpucS=kpB)L`q4Xz=fy^gqStz&( z8H?@CjfV^ynW65hp|JzHGeoEoHw-sH8O|2t&G`M7(!wDKA=BN8;xT1^Ex&+-Q8ad7 zJ^wVTBB=(^T(OeyK}(smv!;E-g1oamV7=Vuq&Pzs^3Ex~b(hn1i>?Lxv0Oonn(N6J z!TjmBSe5l=YqGW3x@>*6A={qao!y@u?rP-V_|oS~_jWfby>jn!gt1=h7;`>^B-uG0 z}$Zb-rRr#gmH{`gqRGQL~0r@bLAeyD3VkJajP4f zzzgUO;%*4`Y-&J(-T8@lNjV6Mh=_S~h=}D(>h10@2hx?wH6&kLZb-~& zzYRx3YY>EuQ=!3Do8y8TSrwIQ+h8w#r?6lG)D-@~Y!h~GP=aJ4bqavo?x3XTTQ?>e zFKSFT4l?I@4AmCAdh_ptA(m@LhYs$9T#!PdqW-PpBU5$(PCiUesH?@wqG>np!)y>8Mi(tFb!>0eAU>dZg8?j_NEr*QOsR5Z6pt^QpjlktC2XlxH{-4V zu2W0Z*}tf(yQ|uLZ~6PxS5;qAeO>jp7`6QV>hD)ST>WVEW7Urfsa5@A^-I-%Zak^+ z(Z=14zi51}^-ebT#_QXgtEfnBfw%q`41zjPX;WFO<9jV|&R&FmXmp(}UsnEd*O{&^3>O{q3zmeO88_Ev#xy640IXkHiCj^ z9e@HLK5MB*qy6%A`!Uf+y zPpq_KP|3&A~ir%4(jTawHhV1G=HSa%6P&Blj|u{1UNk zYHMEvoo?k$;}yKsPsGrYS9}^F4{6eM>@@CvE+7c9dol-Me={^ewSpT@QC1&n{cy@};g5^Cc%5p+*nM z>CxgnBRgLwtq4H%Fu3Od7Wy`xIlkne34swLs2?xoB}6|3_!z+Yek}ErkKK-G=4@$~ zz(YHR411*|BQjYGuBUv0m$TdO1crHf1CB#MA4qvMD5VhzJmT!1BuYGwcvIJk0WOu< zDh^X55%cjbdZ8#shT$f~kyC|Lb-KN1kIC+o)3Sui@{#1Ue4_d{)z8^=xfkc5y@{pLR_1Tws^@-W0T#&VGCkwZ;$quS-P;j6Lf)7EST|7+H z-066kI()gwX?e!ja6QTi;B#_%KnuwX)XQ(H{c9C!&Y<;`ha!KGvql6 z+ot$6T#zRMe*lC+GPE8pGSP68H5kalFg+odP}0(DZu(-rA8# zRE1aU6;?Jo$sE~``Te*7csCjp!vl;Mqr37D(C;gRq#DDWV8Pks6T4G$`h*^7-)>I* z&T-tx@!MHtFFN)NE?m~f6TKoO;RAWIiw5fx&oaaltg!$fR4D`V2EBZJ3T~;HRQPrq zAj}me^7nj^q|0AizRc=*i|KtrS($%>1V&_iB4g=eTaQd*B5qiatOs|mmX~&Dr;N-L z*f%}zk;~PUyof4Je>mBci`$DvcIDJRvX7WGWgfM&_0kJVpRIqYacg6!vERe8MdHZ{ zYVY31tSHM#i14v4J2gP1cjMy?3o>D^4Y^Q!nsflGhPjU*K&H`|`8 zwTRl%T7)_IG54SYLH+2|Qij+f&jn`TPy9zhv>HR9tvLE6=SqVnL;Kb(QfS%?@Z<%f z<;RLSx5m)Q1#!5ROCDz7nd&#NpXA6W`~tRlL}84S1I=wDwxwtoElYAeqFr%&@!6?w z3E7OY6bK3fYL@Oe^$|VI{iG9c$??e(^M~(XX0CCtoxCYlD%oFG=$_zr;&oC5b5aUkN-wSxp;iv%tY^)1^z@Y{gQIUE#yzfgBjh(2_-tq>2I#S7V*chHpSbd zlN9+)T10jL)E(Qe{0}ylBoE&H_ZY$(As2gdo_Y)LA7~a6 zhz3(ps3MXrSLzn0bQZUwd^XI@cn^bj|2w0->BuC7o-L?aHI@q5QVoTZ7I zH_0Y+-Ov?`TbwNssTJsgM5?QPiyU-=2D~6D{|bEoo9v0yHiXGB7m3$JVlkpP&(_1Ec*T z`?V3Fc_U|vSAr2D|1}_tcEaj3E^b_cvNL3f`XciK;BSb-q$OoK6i(E(@zFzj0OYi( zP4Y6|xdoyxRhSi#S+p8|*SMExC)MQ(D*wpB4A~8)Ef2~8Y^C&9xT-|-(xH+qc|?*& z%y0#zVUcQPx3u|g%fDOO3Z2Xk981fC+c}>5ap0Fl8J%ajd6D`5L%L9~bs0E}kdwLc zO9SIB%7*bV+?pb^;|$K1 z@WIMmmv&u)I6ck2ka}Rp)SEt@v!{9_q+oCkEpp?_+!vbHHWl3k9ZoLdUXN%}`CIB! z8z=i2t;C6yuvIUwKE(&SS2SB>#IyvYT&Kr{>j!`mmpMZu*0=?~*v<}^}5W~c_Vm+e&(8v^}%`rL( z@nl(U6{;X*jY;kD^ozNzNry_O052LHhdGEFGKyxUA3r5tRcnbYYJIBpxv1W$i6EsP z$ddZ6?bP#SHV_g02Ol8|fn=enfNkOuV=52~!qejO0>rP9*rLDbJ3M&Kgth3esV$%! zJXui2T;N|%JJC0;j#XK4xUHCGwL$RaTV`e ztVKRu8s{`B#cTqHd%1QFjey?vx#ZL17uzRXfG+lFE0?Fs2VDPBR|~clAg}+B!%TI^ zlR8`^`zun&Q=DhX&0Rh%M0Hda#J?5;Lyy10e$f_>dEhu6xh-13IA^4I&_QxN9X?4e zKj&v9$r=4w?JR2Z8T4&=*pksySeFrHZ*{b4W6iH-E0r2KF!Ta>6E6^7hfm~Z@}6na zqDm_#Rd-=^T~^7H-reORR%*&%=NXV%oei383JOENSABAIy@7mNh3U@I9rM4C zzdqn22dqh7x(CxUv5nibzR<(bcXuvCOi;@ZM{~i*f{LOBHWdBR@Sq!-HbCs)q z!$hvB+THjrLsNzM?EcH{&-x+o3y3YHhEvw&S_h$FqU|)W5f4MHGy(ES1Rn$Y92CaQ zYu7h7HlN>QN(3(+$W{ww;gZk&x414e;>Qcp<6&qYDVHlNs~J_1Pc%N+_;lm1Tko)r zxrJS(Qx$LQOk=Y=$A(77ntYVQ)QC;LjT4|`C5D7&C0~K|PrMV?7KfnYGo8gy64>x( zb}-LG&aM&;W8-BFN(Hh~IH#H{pR?w1crNqf;)jvALA}YrpncLR5lnC~4?6FMW(Vnq z7F4fq40CyVVRHC`=3vS!?^QY_7gesWXDc+fn!~wHFa)t|>gCuS(6AUm{-9rD_-UOyQ0&E5$|~ey_!Wx+tZoXq=2KZcM^4GXu-ag-E~w za$SJ9;%PVZOS4CZP&7oZO(Y|s8tVU8|EK!Db@E1Q*?%H1d^;1`8`1m~qYE$zkmgWv zc4T>&x!*kXMzFI81rvKB-@$?%J(XRW!^@JJo%*mA*lb8`M6leOI5K4C1V$G=%bX2y zKFMePRCJWeS4@6A6PvDT-Ql35;8ZzVB{aG7LYF2M)8>iR|H&FmpLoFyH{PIQiqotF z4tjyA1-HwKo#rVKNtska^UHAC2H$NgL3jD9wYSvYiWp3wmk7pSTO)*wZpgb5k4orw zTxTa5qrMKS?*LE4F8E~@j}yC?^^>$M!D-8Cz-hajCD#w4hS5XzJZHZu?O{Am2+-G-|j2>k8|1wi1LG z4NALF|M=&c%psL|XLezBadv6;=tY>0=Vde5q3jp4U&~&e-Ie`b_Kxh`*`H(|1?%w_ z*{8F6vVQ{e@z2@6X8)djJNr)d-RyhW53(O-|C9YFdpJ9ioy<;Ua~V~huCA_9SEZ{C zI;4rq{CwusBnm}Pq2KL#uTY9=$`QUo8Dn>E)$gFa2ie&eE$&uP(i& z^xD#0rMHxRPpFd8eQ+E9d+9$*-!6T(^u5xLN^{+f^6K)9<)13QsC;+%6Xj2qKUMy0 z`JVFMmcLm3$MXH<2g+Y6|8x1v<$o#vTlp*Hua>`7Szfu2s^3+W-pT#5h&6T?< zZ>hYs^0vx5D9FCI@`1|lS3X!}qLUn`t%S*}zUHa2%((>$`z`6R6*_A|<7wpoCm1?- zMbzWQaa4nbh}hMAa@J)3#h$lW>hSo0rZDZ6Y6^F&{tb9DZ*D+d&o)1kLR!DScD>zx z8}l4)K;pPmy_NJ{8zen4JrgFKN#cc%&S~vzrXY1Qwbwd~7dr7ItE4tRyUl0zCy-LY zRlNc1X{r+Y;h7tDj_r}b27^v0M(Py>DbBeyGw>^I@~AXP7f2>cCuKPG3#U1$acUs` zI#Qi=&hOmXRkD(D)h+!uWzWtAkgacOGInXs+@lZHHq{>k+vqpo8~racj{g7gjjnwJ z#?k$7j=rby2d!tf23se+saT{*+QcGwv&yJ{3OLJo-Ys_AP=>s)>&l<~X1z9P7P1wG zlmJ`w+Gc3sp7xSZRj1$QOlIV5Ll+|c-}mW9sq_9Q%;#A(1~Y&@Uw zf)b++sN;!CvWrv~KQOY#l?-j_g1Gmuv-1*Aes~z4W@reYwDLcwB_ME@(z&le!Kjwh z^F^;a)s41kGa=C5 zTY6uPLNEOR?c@#206}MH)b9G{>YuMe|4+SmVy_s}bBk{2GzV4C!-Ykc(q@@v|J60S zBEpQ>2jLHjSIc8U5Au#vc%hyR7WP!%J^E`#{cIbbn3>4)A?#Ln_UKqKr!EM?6+4Zf zsoRA?c|@~!ld~RSIM^3qHO{@PXo1c&*MH zdd_3#E#(2{%^hf!=Q$%Q<}075TJ{v0-e`Ff-*E-HP>Mb6RQ){3Fuq=J6Kc1ipVwzQ z$7crif?N&c|GWLg@cVVq5$LzLs5h}-=iZ|tjsFP$V*_sfAqS}Cyx9aAc(lZzkDI94 zn6%JT^yk1H@YGtnb;BZK;EXaU6RzuFP*?j<7srF+}3zjW5`bnd@@bP z;o)$Bv8e~p#kqe$(_a0DUVOc3oPa(jI!Hz-`R`<0yU&96pzPHikbK>6a$qlwwA}(~ zFI9XUg7MSb?yR6ygS|EmHE#)>zha0SYojp*$O=Jo9ft|w(F>khyFa1XE{_d|uC zbnP~RUrynudWM~Lo4*L8k#Z!)z<9AM<#&|dS^hxz56VF;xn+csjq9YducZT1v~&8k z!*BGm$&BFyMIZui=|xKJ6Qt%T2WLUTLh-ymg|;koc_&3lWXp}gce0p;IPn>GU86l+ z9ZDG&%%RF=Jiz?Rt$Oopw>UBUT&DwrXWVqVakJ#6O#!{YN9CHByMP2;A>$!Hz|L_B zzvvO|-Q5D!=ns7c7&wRuhjws5DDXQvVsTxBdP`h%^3~bJagjXwB`yFd)D-N=RCWCN zv46^c9i#+)8e|_M6H9zg^tQZFjJwjyqwOCREhB6*sx8_>NXK;OobcxYZF6zw#gBZM zc4rIu9l{uwF!`mEblz?0-MM|!vtDrhv#!@~<4G%ARn3=w!NRG<1`Gv1qAc4pP>=R5Od&fryVL*xe z7|lS4fpfb>vR5DiS#*%%Dc^Ws(QZOi;_+F^zLh+TPVt`Us#y?l;mWJ>mg0{e6g$I) z{{17-$&No{U9Uby&c-m&T`YpgDbDOG)^3+YXH~nh{!=awF*%C!E`t3$@vi0RSW-Wf zmsDxV0z}|iVysa4yEL;JUbS~*SeQ6hy0t-YXKNq&+IaB}OX^`cmL(5crEUg9l`kQ+ zrtF=eL4M3O@K3GDTsjg!A&v+QsgcDPc{?-BC;!NvRmE%dVu3q)TYWw1w zf~rxUz!gM`r0fib=KDE+w3Ohcu}FKzn$vs*YJlL;Gb`EEZv5PD*2#WP-0#wRRdoagd#m8^C!# zH+KMgnb5>gCo2N#Pw8UvAguJ2)Hf)|Y=-&r)R ze5m=tYU(#)xXp@_8lG$A79(O@Wxls`Zhxb z(9yYF?l{G@%WF?o8{)1pvL}E{202}kBw@c`%sY$x7b#Wub?AqVelMTRtgxe2zOuQi z`O2PrqBK=JB~M5*50L=`rDXi9z6T!w2ndQ}Lx}aDoju1TmA|aq6NET&GIb?W!%UDP z!SORT0XhG+J+hCf0oX{OnCYyNo=#AngOsis%u`dOsWy@*(qp!1@Xs4F_mIA@18d=o zk&Ch?E4Ka%+$8l06Q1~}urt+>F?jqOZ81jsl~gDw{3;`*qKKiRxJb+^S1APVPIDmi zPCLh~wOLLg@*bJpc9!t)I(b@KNUe-ussVdU4qiW;MtT2H<9O&cxrJ`DNpK|A=)_lZ zgWWfl=7V8zhgpiD1@6M>xARshuU{(r;d%+xg47BI>T z1)#p=AX{T7qwdkYs{F1BtXqNnl3ugxR?2o(=CT%fgIg>-I-HCUJl9Pg(nRZ=zENe^ z>gI9+LD+LuC5=u5eTm=b?k)%AMSUGcksK72~SZ)#I&}){%APTZyW-@_4!n z8aUuy9k~M)#uwDPS9PD$eV$ctibyw(h`*b^2Z1dQKwY&x*jPV6byrr6BeyUke)^8o zD3jV0xrsX9-%@>R^)Kjv|6}M89CV~uUTdqFJz_`$V`v+9d}kI@obo747o8YL!Bakc z0ujK1UVv(3NjvL^9UkT+mVSujx61Uuy04&Cbg}$uC`$d?aT#=f6QL9tEnT%)U~CbvNfy zD5N9+!gty3_Ql36z?*9;PJkH%U6l&v>6DApQbslT{6+bw%rKdC^-cAyjtDsGhUpmj z>kW4@h9GT?6838+flr0BXv@{VcZkt$F0>E<$e&_8XaC9dgHj3CaIHqH%2eVf*W z=kz8hwkTRV^4k_w&D~1)h7!+s_DEF-4Tegcdf$)7;eXR z(TGg*>88!sHp{W%333;NPC}&>WNTvr2B!rJbHS96Dso0bVlgy3`+9XBV8j&`)Y7wj z;cVH&MNy0qYAsgo8^(DizbDGQN4T2AN5I;i?uD2WZ+}vaHfRf5oY24o&L70{pR*KY}*EBLM=I`Xf<1mGOl#JINCSs5e4j&J%@E2p|F{M zn+)e#WD4_0N1kcnRUng}&v-1WViNY5B49zAdH8g;Dj{_l&1}dneiM&0ceADz;e}7&Z6+R5v?Gy< zyoW90yRjkL4;Ev0p{_k!hDV6jHYn)w?Cf~?{9T>N=(@bSjtki4a^+> zC68Ew1P9VAxPr!S@14qtODwMU!tToOKI!m5WKN&W-LH6WeN2o}@`m5JZSM#j6i#vS zHV=OnN8W-?+eTkJI#IVkeW7Mutq6m?~cuKFU^7*~Zcr)2Ieb)_u7XXoaax z+LpWW8d5pV1&>QjRwXeD-x@)M2R=VwvwGVmK)=s}J?*Xa%YlB*IhnrSV6s78l~3?(*1G(G^QY4^$9Q^&Nc& zsTQ3Qht7UF(hUquIZ#j%`4|s=7KpHP54ml=K-O?Hk;jwX)^hhL#b5k@cb$CruF7+L zE0WBD)^drS^~l%EK%9z$7A?W_98{EAf5$*ENoVSx2?1c;{xB$c^1*Dn(aD$Cu(pSu zpd*jJECK6{;n9N4eb>x&0|G3wG#Es0D6hh6Sle&rS&Z=Z)gZHdde~{8qkcuRQVVU@b*ZDRw^%G*8j?$s= zC-X1XYc7CTn{QOM2jk1~w|)A4I9XXn4!*K}C^OAU<-)^%1@_#rH3%Ols_=><8Sh_U zT9aHc3sw z11PTkDMlMFN>j@ku@kCpC*DRq7Y$;{H%EF>wmzI3!{~x`A;t?^UqU&Wt zc?dS+MW2^3TS_|f&`!wX=|N7;aimb6N~=VN;9HgG2VP`YG{2j;K+r`GL|o(|?G~rH zt)haJb0;)HftJ(}`5dHD434LywQvj(icvChcvIFxEQK;DW(hx(ofif-{O|UmW@$f% z@5BB`Q$UbH;gu5yF(A!a3TxXV;^pY47&?!-__4VG2_#@LDD`$taPsUcI@m|&w3Mzi zvvF)#`IhF(1J@k+tf4_0$~FC?`P2`3d4y*o5oV4jCWyn2!x4|38om8p_6&kx788TV z;JG_`>eqS=7X+Y|i257rf6kv=;?2?GF%B-!;;M}-@gUNeoMj#-w*mA_F&dIv7+{Ib zQeT4wQ{D_`r9B|2F*x4l!ek1m?v-b}ytBi=8Qci5hQbt5zII`;1{ZwH8z(3MC=}{S;rI-zRPx;JM2nDq#$#xVo7cNS?jN1r{Xl4 zqe!apitJmOI9q#M?cadGXyh&cn1)8}%9p&_BX%`lHvlg&U^k7|Z9N-C+2zDNfw5?N zjg-7dAO}bxLcIu2v#H7$q_jTD=pq1PTB6ekGRu~ue)xno9vvsjWo*k{5fJFQli$fM z<5TC&CPPOkldzY%EJQ{DpPl`1n!~Gpz&NQ3TJcD{gYhIC$Y>(PF!> zMxe+sd8oP=mfq@lXsFB6#fys$9hVc8F-6qmoI!J;AFLZf_utv!j1E8`X73e0k>N23 zeR(4nm7B*~%UUa16lz#OT(5M(;hd2lsnx}qYK0%8^r`OLCKo=3>X&3{Xpk_d?Ux;Y zRBWXdy5G({IclOGSK#tU-8DN33W{>V)stG1l;e6Y!w3b*%MQ~2TJG+~`Hjako|yH7 z46nZa`Wy6gFl3$MkY;i}IklW+NnROwg%w&lBxOnt!VI_wIcv|%dSKid;Y^Puf|KsX zFEoCs@hfJA;62c*vTk}KNBw#vf(|7q+T>OaKRQ)1nL@vwev0T^1vkET;%;jzJXc&y z3q&vP8`6EH7_j$DC^|k0D39Ae8!y{0TVX)_T>aBb_yXV_2HEJ~oVyc9PfJCJwXOkZ zPf8%PpKog(ZyRVH6^7y6gcC@V`hi8?6oI8+xW~AqiN#_+9UrmF@X#%u6_=wkB z6uK$}KvSE>X#4A%OcX(MRjcZ`)R%eqYIZXM?_q?H`>KrXJ~>ihL6+-U1)DtwO(ywq zD3!fZtS=y8jTKE)nksmBZGrSidAkTufR;}GPgW1A+R(DabObs4n+A)TwXG)0_b`kr zC@UPb37kSzQP@xVLc+-lj=eJ+JXuLS4T+l&7Q4qMK|t{%+eQwIPv_%o*g$djP(h6( zAkd;`3DXE;hKBp5(74yQE$wC?%g4;?LJQG?KlD&rnjt^U79>NvzPyp9vtmXczk+QJ zx$Aa5R)a}d(j(t;z|c-+Bfk2z*?&wfBTUkO7K%kYdeEOo%#Hb_-s1br|4dM|yI+w| z#Y@~>{&w{-)yF!l3#?e%1Ug`GWY91bwhWw(dFexy?^B?bzFkA9KU{Slbp8d|N&=KU zq!Fed>KdO>3QH%f<)cGFB)}fe^H=E>*^XXOE>?%5xuZFhT{W1-qzX!+=~fHsgpuRo z%}>I-#gF%5c@ZGT6{k=7qxB4Q?SQ5!)G%)kev)DxJ^tCAy!Yo_pInM5wt8u>tL~-K zLm z_Kf5WU92X2+c};xhI(L9e)1sDz0@j0`YC|&$$C%d@h22*n!{i;_qKy^XWo>%;E7_s z2lZ@OdgNiLMb+6(U`#zCRNphQq@yEP0SN|r>VfPr78e^}&P@WEq}B?b+}z1L!hF&} z=86!4DP_fz>p;?iPkX@-c(Zg)uBfVg@Y3j4z;7Fv-nN%m)6p6BRE_06W8E9NM^pBN zDV2kH408Pcq7CWu0KU!L*>XuncxFkPx(QYXg3cp+(@2C$WP27usg-IrvEEy(y7MfR zf&B5kS zb5C<`bENsgo}Qj%J?HdX+;d6K<9nXab9K+pG2<>p2szV`4RQA}VjR5zJsFeug_H^X zw8yS-a$+q7D_jx#t_TJkJa|AlYp7@;Dtzt9r{ta50I$$xIw61(V6B#6#>H@CZ;B|7 zw{QPpSo!v){xI@Lf0$bM2Rpiio9puu(Baqkxn%|VNm9Et*iUm=4oXNaH}27*YXp*w zih%WG0<*g6fpeF1vpMrb3hZ2!qLBvmmv2*lxrzGAaCM|QU8M~mPLE0TLF(C4*7CiX zn7lx?@ZDXR>Pm%_qx(LQP)K zvH>Qiobl^`LobO7^@B@Y!7QK4;tJlML{ZKpBfAstz+#oFcQ#(vczxroVvp6&%Jo_N zYg`uz^DFZEJ<_TaSEgU?OIWnUceF|=UNkzM9%minIh-sYbO3F5Jq$#;5m`5NVqN!ij+ za!6*CZ*|vJ*UxG`#(5}Q?4d~DNfc;W*KtqkT9pt#pc$tO&h<;$)(prwYY#>5L>o zhcFoMM*MT@8xC?fu0u%gY2gf+>ZFUld&3Le*Md1~{td9IDq|6N-2r?(-?XAkG6OQm52q9NY z2+vZuaFK3{!R;3z6N(pOlUT8ZYn>O}|{a}!17Dm)AwX%hFh>yxblE~Zb8F|(W(Zu?Xm5y(aup^139 ze6Cj%?Mc7LvN#ZAs$-?Gr0bLlnK-n1ouT-K;F1bCMN}#^#{#9q)%k$Z;PaM97ZD$1 zOH2!sQm@=|^|1 zE)M{H9Lue|W9nDpYNx1BUQB>j8Dv)UG8TLzC|JrUO~oEYZ19V77hpLi2L;E~rk!A* zg5+PJm*wq&@DCjsIjO)!6i9Va3-Cf-3j?vB{q=MEGxi7fl|r9u@0`1eQ?%}ld^<;6ZWurd$o`W5h0tOb z^bNVhXdbf6F1PUqYUAos-9bagz}_YP{EqArv^kaF$k6X3y`X{=3LL|0f9I<<1Cb95 z^g^g}BDhCo%Un3v8ei5ElD@eBRL#t&nWycarmD2h){}_yV9FXDaw;8tW?d?U@kx6C zw~p+d#0=?9^gC%zN2(R;lew?kD_lQ3jBkV4B;hGZw=!I1)wF#`1gU`%(JE`UR<=xr zcAD0veeIl@ay<)2U3pX9)f~y-tGx}sNsoJ!It2n;3=Qzsb&C$Yau)NP)DS>jc+0Iq z}i*s*SH6(Y~MTvbH^u)t{4)h$KZcLkCr#oL(q6 z{ynQ%HV4;6zr@p546tAA%&71qy_U_!&w^jQEibCO<{VBH5%rsFrRst+p<%k{QP;{Nka9(Ne zaG(s5_rAz;xFFngr|T&k=#q|cD-xAFAVgoEI>%za2u1>()&yjQyWoXo$dNYqKv<4?-#T%UU~4XSSiDY-kzf zM=_u0wnsMxT0{(e90^*s1ieQ)$(P4tO9P(ylh_XVld3I9(ZD|EateoT{&&)hgVdP7 z^%Vn{;@^6j_HYeZ^c|l6lqU|4y&HxKDxMs#aMBvrHh#LX8SSQEMYMP!vdxz^e~nBS zWp}_*WcT_;}l)48!i-YBX`M3pEWW;+bnF492 zvrEPg#FJ@$E&d}5@$wrYG z7qk_JJh?K!qsaUpR!R&daJ{zXuMvStq9J;q&I)3_0wRTib9V3UvED> zHyE8h*lNOepL?ab1XZ~-%XKLCa}@lLW1u=s>7*F(d-8um{+yz;f_xwhgr-)tmt05T zU6hTD{=;fuTfCh3{;Sac!_-P$sFSys6j9{|)yHKQf;Aolp;-tZRy}9npMQG>Z3$6W zibySP^)J@HRR1y@LcmnqT$YRig6n*vPI>e9TG+}xqbl+dd1)fTy z+jM>H$&IU65(#D4Y8QpK(^5dxtCD>RJA~okw&6W?ifB{tPkE>kELuyJDNw;GNpDB4DSX%m&1p zN(aNi0@Y9z9xNk6&xFy?`pzUjmGC_E4{n*ro0^koqp(B7p>v3KV= zeb0jKc+uzr@nl=w*9+O-kjV+HUKp+e3!L0*^oAzTdT9}VapPfsox8k+w$U}?gYHr} z{Al_Q6EY8#k$}_r$X7WTPQ!?Oe~g`ercZvkK3$)wzpDP4e9BDjNb9Iwlm@Zsoqg2H zt%26tTJLVXH(RxD$bhYO?~s;D+{=M44ir|{!1{UhYZ_m&-(bhYs7X8cl^<3wz*$e3 zk_9;uh&R+}1@;mp8fHV~HCr$$>u$bGfMp)_^eUx_ZW%gQWYGv`34z@5A}L6Wa#SFd zf^}jxX+F5aBMe7eiLRw=^eVt_T7y8Jg7l3Kj{m0=q%q*mG=<(Rx-__}TUB~JHraax zV2X$8oM6U~h;uZRZF~xnr$HKwigS7TS|5S6*htdNiNDb#UnD=UJX0?B#OyF0=JYuR z5Ed?1f*f}`UFUPm-MQ>W^w6QHYICo3bKyGU!}n$NaUYjh>DF=BnMnS-evUuw*I{#& zK@J23GF|SPO=u)}gvEdpFKey(!|KWUqnpo!F7X9DbeUq-od$M<4wdy9YlsDdV*7XC9i|NwrAZh$@n{$y4io zI3ZyF3r!BIZ}oZB<nf$M zJwXk3&CaOI*vW?(X@egRmN)lvjt46sa%oNbJiD+t3=TuW@E0gNCDvVjFfLr*G3Y@s z`|w#7da2T3PM!Jm7oP5^s})l1VBiSrIv~<-7vHoxCq8C_vJMn`XdeA22{)`IE;D}Y z5??rLBD!}(6sdbqk-Z@I3G#wnj%wuXU+t_wn{TjR;agHbJpVT9m^EO~qZ4fQ8Yx_R>zx{n3~wS^$^`*_@}(Q_l}{;G9;`f6 z`C(;Nljnx^#i`_8V6PNWb<9iiad7PyqDw1B)HCITknrp|)tcqrB#GE%#A$ZcCuh^t z>g!d@@uAXAz7F6jkX*wRRDpR#b{PtwPhOAkxM%bnax3z6ik$$mjLRrYDZeRJ775;! zS$#L74b{O!rRi)*&|3D3f8A9F`4Q^S|ZDB8y@D@s%bQfbh zH;nJ;!00PcD%Ojt^#puBXSGsNp+RPU8P;8ve9cs2eO|8|do;pgBWK7sL zt>7%9S5u8kSfCeBQyP#bV z0>CZdHUWgxPyvsLSwq-jy&0gR>Yzdavr2cp3hLySItD{mZ>FSTUxox*n~`?45~l1N z10ae{qSZwfTiSa4fx+?h10(hgXFm@>G>=ni3D@xT#%hq)WVd-yoPfML!)BrDQar8d zs1a2%6V>0Ttu~Pb3X4bY_mM$;-fsKAaFPph1V`M4KB|6|qP2;r!e!H)P1?LLQ>U84 z=pHR_9Mi6!FAb=)l;G=u*3>H!NCW9O5U74V3ufo%Q+e7G3l|~Fj=j}og2kUcl%1>S zTmin?{W`pc6Zhs*63(as^Q5O9a?OamBQPkoBayW6m$}0_`H7W)U@_>&Evb+bXrdDo z#&({O!bm=O|4;WQPm4029?Bg&7HO^Bi5;}~r=$$!U&#+~3h~<*c~a3qTdh1TJ9`jG z2T%|=bxY7|1inl?Jn>_L9vl00VvOC&UtN8zl>6tbyKVp38bR z+4+%!So)7rO&t@z?4rYtd!v*|#L1nt7N^6ISEp<6z1vlo{4Wa2lFm^4gaT&D-|_=M zU;`23gb=KIb5HXQcedvz{e~pl#t*n#t&mUp6-2(R*@Xttvk*{$)rJI))rubd2Q_;t zM@Pg%^}n6g?K)mzQYJP~6J8~J<>RecyAv#7(P4Y~^;A!-*bShN%tIv{pHLIu?NhMF zUz4&}i;(N16O0*B2@!qB6H!xUeDvO-g9E~!B3~5CRdBXIf$A3Md3)*!3S*mlLbMZ} z?HE5#bcOfWb7jv@Fn;YR(RV9ORCywu{xY1Xq5xfst+b5?{0vMkKh><-1#OBRpBkac zl-lN4f{4;{=K&6UMolbN+Vi0_o%u^2 z)v}QH^6VFs33gPQ^~@a8LP!@mEPjBb%2~1C*4`2x)ueff9U~N=En@J+$oJ+2LJ$9z z|G9oLK=gp>P^F4&U6sX8uwD40(#OaNVV??{L3|H!w-W*L-!zb7A-6S8!+iD_;O7dN zUhLR8%p**RX#JZwpeOJJR)M_e>8SFGs@UjGUIf3bi5xuh;njSgZq-VrE!rT_jOSn zHJr~0FrxcY;2+bee&kCootYX^;!&{PT~v3*=p0)x({huYrM&lRAtXu_=9QlLdMW6~CVW4lJ$M5zq1Q#gVW zw|^Lp2#XwyVB0A+-?E_%LAfVu9B9{w=E@N?C#Ql68=@82L90ADT&fDFSU_Gtn@4?K zpK2|lPsmaSQHnlw#Wbqyx|Y79v*Z9UKil0U>q)E6X}G61C?CA@}@H`483LDW8~3fULpTKpIi! zUxW^bD1xvQBbuHPH(Ajc39`Q7+Xx9#El{sIpw=BGrrRSVTRcPME~+6F)5=`fbs3Ni zd zj15#Unlq-l2G1i&^F71bF=w2WS!r~Af}WKX)m7E=@_;((#i&K%>DW6<_dyPI^iTyh zgbx=|L0!ZNA@)ja^1Td*ve{dj6zJw8}Zq%M)$7`4>?M2-1RLE1v^j zttStN#m50UTUSM<*-0X{YlUA!hf3#H#Xj(RHu&u+CJdQ0`I}y@A_jPY)fvF1B2o1C zw+VVMcNc{#fR>;B#YbhUb^FL%Exwp81dABt&>8jCvhsqfif z^&VsfxOB$XjQ`mMfyKbY&cyd26TuvWA|{A{QtSd)L?ln=w3rb>9$Sf+l;^}^&OxET z7-`-8xZF6DC3!2g2m#JZ!>jejBk%Gb+eNEI`4-}EfmgR%&oGRcCF?HV$(jF{YC{fv zqRY1<0BQnL1SS|s`?-HWcjam3sYPjKyTvKp*}vPtJI@5Z@*I0XG(xa?sgkLu1ziV) zo3mZjpQu77pc)6mDDCQnKS(wGmz6McG(Ocg zmRdxImHpWsBN|=OO0COb&F*0IhSGfq8N-dSk@gUtYcQ!va2!&~Dt|LuH9Q2KV%H4p zakpvg@Syu@XknrWQt7D3NlHUX5r4(eoCG<86(%8&n_6KFX-T zTuYJ!EleC~(8siG@)9@g*~@iP#>&c?L4FjzL0;&UNb_=e+qK+={7+zb+J8C+zX*uZ zet3e|;od2S-1?%KPK0Gi-fK=0z&e8SH5`zMBlh||am1qpt#x@EG7e{{`j;DQz1wB3 zozYPo)1sYSz!ZB6BL8L!)~*%5Biw+U55Zq&1$A~#Q%KxFk=tO!PirHUTs@#Vj=fg z8iepYP0FhusUL4t=mf7fRvMjk5eR^r8&9Pexfz638YI)Wy>X~#xX6K%j{edaH>^pACfz@mD*j}ff9}3KqXShDyxD9eW$t=To{NZDw-1uEDe7@ za;}eLV10DN*yZ_;dzpfs?TlqoDzGE-;53L2cVrP#eXH&F@(edPvXj@GHqM?!c>9N$ zxPgE=L#snTC5=c#APOvFde#()fT!oTBLG051sjCk(RDG)e&{VHr%v_@e(yK$d}U;z z(tNP_F!PmnwVt1o&Me9dAVgrV+*+&9e3Ypn)1yP}{Dh|J@+e^DfpqTK@+|yJD*70E zoDV)9EGrrI*-R=dT`=C z&~c=?I<0xX{ZR;7ky8&O5a7*F@EHWyC`kD51C_EIvTIRD|8XikvYH#$tbX>cTWwHa zk>Qg*upX(0>GaRq*AD-uZ)}IS(xhX|&4zhsTS`d-69)9c?EzoBFay4r*0=>msD6|q zQaHI_f9JleNN@-uk>FX@%`5lUE>~xW%xuA5*zql2^OeefWga+m(@i(&w{fl%1Sx=_ zI0UpWjsj!QLyIdd15$~)ucjaC7Txn@FfUWa^>x+?xEU#eiwQ=<7H>nPgCh%%L&;;S z&S)x&_LW=!9aCn{&&D&&TLM-*k{DshgSJEn9fYC!f#Y_03XDY=_K3r5AYd51ME@v} z7SGt-_|t3X6>;H$lct%&Izy&3Iye66Atn!pbXDbjN-^|N`;r?59&2v zZwBl2EPg1aUw{XUGME}F#0-yjB3A*;fMD2JJpP1~J{fPbWU~K4Aw%iLY3DwxfU;_z7-2yc3v+Gvg_il*FmyF3}En2SSOkmaolTbHyR?#3W$3$nfyEkTNN+WDBzj}&E>L4S=a zb^2}^iW=AHfVK*KE}C-DT5q;OCV>Z*lL{zCTUEb|yt7*M<<(bIUs-)s6%2+plN7Ohn3PXD-OXW>aI^Nd$ zMz#cz+y*Ksl9wU>Sw`CsI0T(X65!XB%eST{l}SjK``?lfhOGsmr}V?pk7|$gNDPT# z?{I_OpP$VgB5*$G)i31FTIoF9andizTcYkwZw=?*)B$_Ql5wX|jK)30cC%1V5#5Cw zRL$Oy{dx8m*_{ri<_$Qp4ymnCr?81h${1M#6EN%&zR3{eHZ#o%crLJ2$Yz(^FSAG$ z6j3d~hBrxMcgaPoAr=Kot-!5xc1dXlM6kw~F(1)}B7sSw_P7|vrr|t?R0$g9^5w>Z zn$%Pb>|$ z`W}ezMk|};_ssXS64Yc&sYuFSBB_+;0?MW~9NILb@{Hh|B>WMr!zPByS8jc&^`BO_ zeo!ggr3~eHZ}$EQ9R;g1)#uZW=C<1F7&*qAz~-kI&LHhp0 zr5%+C=1C&Fp>WIf{+eAlRlvu5nTBX`)RRt?H1aPW$;+I3$KJvja3saINwBGyJFkLT z&1n*5k>DcGQs5#w{cGi~?VpOV0lLX$fJmaevo7fD)H7AjHTx~XIYA4PVZpef2@N(h zpG6lb_}HNQjIwgt^r#N$em<|NAcrHgkaecPeXsT;&vCoWk1cEsN_LukfR7U$5qXTm zhd^(5jII59@@Q*qgcoHo#l1wJN`rd(Rs2r~7+d=|tn7f=+qrOv&A#{h_)2Ewh^DOX z?7t8ASOnrQv^aRr5c;-t2n(nqrx4`O3$g}9Kar1^J=;d^hBSL(1ta28f~38ry)9P& z$)VkZk>RcfAh34hxr6rz!A+hP2-SqUxUwP@<^1bqPN7nMbg8vRt}8I7{*(|><5Y6| z`Sjr5r?@{T49amx#CT6CJpn?*Na{6cz7ntvXuNsiD`D)b;uE<51{LHgDfemN>LgtS zqFR=QfW|_*+0m+AG6I#-SF#!ykjDNTh_Xukk%S=mTr)ZI}K83mA#D%JZU@7^X!Zq&XFMe|3n zcAKD>^j;&xA5}ae3IISnpyLKcRHVI;r>CX1?zX2`%N~?HEW4`w&Dxu?#sn{#lu!LL z_0Pfrpa*9_|I{W+yX2ED*q{h}2F%b{xi2@!=Vy&I|X>tk9$7c<^PyeplDH%as3WNsd&5#i8)$yi6foh`j_aK`}KPjWmB#63t8sqx`N z>X$ytuE;=LV-AEM5StF!pCjkN*s`^^a^4GIIF|ZSV^>F%S6xZ+beeAFWI@I^I}#*w z-V)7AN`r$ytu79v$RB#jqyNsBnLyb18`;!DUjqE(^>m|YW1 z@ML$uD|=B+!O5I2lF|f&tkkjd1e~k{pY!t^`$tbk0vRF|ip~j}c>Fqncp!-=!FeV3 zlJ;}lv3{U5SN;&p?Q410DYaSS1pK)6)7sB!2W!V6$34ts<@FHc2B65zn7dlg4W&#_ zjXXQ;p%gI-13)6x10vFYnIWo&BXS)aN&|0E5T)^R{)opcf?JU;fMso+m+ zA0yER{>nbl0H3dgEiochJ)Pz{bgR~<5vwqO%cs6txuf!DmA6##KNcgj^gHEKoK2xD ztp(9@3^-9L_1I2pk@?ZRllX-9?!7mzY4G9jRT>lRk9Ib2fsG`hiVLX!Rs=;ugR-&O zs{K2xC=$HjCr>SL#b761i*}%hii%N8aKeQV0*I4UMX+Y3`JPspiE)}8=*kUS#zPyr zKY%(DKPWB{kU5uFtf+1CaJYDU>EQAJKgPje`drG;Lngsf(N?P86z|{+hP45ev79|o ze$>hZ?nkV&i?N=L&uQRDnzy%8C@%%4d}#TUfFnUXRuiAID5AYk=2K8!{N9pa`{~aF`oA5QJg=;A<_cj#nYOq_80R6l> z0z_+9X+EcUTl4p_Gvuglre#y=br@lxgB+E|*_7qA`iVf#89113WB@otyj-+eT2lUW zby%GY6*$tU0dG;Sci?U;S-(fwk`2=-0+Z`ddyvpEo*f|mlpG&PY<#^DRZ(c=o3_Jo zFfaAMZN^mKQePtpC_SpQGL7?Dz&Yi|hhcQMNK+Qra~ULpP{5^qq01E7_sDd1Mvy%G z`U*vYbRx~n5OYd?U{m5+lBdRvwIDw|01}Ua-St^+T$TSH8s^h#bMclf7PRe)nk2!CL+_(R^$fIn#XOYE#An5~s6Km!@$lHFyjke)d)cliJk%_1XcMPbhz z1E~@PtfwU=XYlwBQ}{bJ1KcjoLiAv&lzvj)Tz+R@j6{10g7PCA{+JW&;?<3`t2X*?}K}$;?ozrN8yFmAqi_ z^zz?wULuYdFbOUs%SJZkd~N{enGm? zmsH0_pyD^{3wU3x(o@uj*RfN*nbdw3&yvh7CD}-iTU!M_$F3fKrsGN_T;&b8YG&cP zo;E-DXULLI-CwEZkm*;NX^-4?@@~Stb09juvJ56KS;{fD^5qz~sDy9C-aXk~<+;pE zqOEQpNd$!jEW0=}k_D@f&~#d$3$yyRr*2uJXTp^~lkKJ*UbM}mi{c(p94ujTi|m-Y zv_vZl&s+YD?Uj|M?m?WdR&L#4Og70*V)zCJlRDkuZr$8coqKZTwvVc$vWf8$g8e6z z#kI?7SJb|ywt)^+ku&4AHr2DA^s!T*owMT(f5HnEHMS}0GTZCWIbvrdbKzY+2lZQXg36;lb`(|3NnthcSD23Z>#ZUxt6h^LZ+lDMa{g#UYU1Iy-0=k6s4JSODZW=wFfjKo+EC~>;*PSi3 zgs_CKBoG_>hp|Gzq)!y_3x_(YfEasQ`=E{ckL6kPu4zF`*iIy_4DdC z*8iKXia#kv)L%;9?T0s3G}ef)(im(EHD26oG+)>Jv*w-j1-`rajaI2O)?UG9vq^?vK17-B2gSCyF{;pQJYhWg*8Iy!GvDjAQYMKmz~-&%j;3L_6Qj z&UY&dPFA~(%Az0vP%T2ft~zwsS7UE2|I8n)e5RvG8iClj0G?EoVkg<^O6|3^H-aTB z3Gi!`!w)?*lgZ?f2r%)rxgS-sOZwG$pUM>31iwhN`5Ag4e4TCxk`E7Ex3gF&zr6Lr z){Bkbn$TKs2BB-nJr?+z7EXt%5}h8i^SFvTS`uQerNnR?6fa;n>#jpDwtPZEByV$~ zB|7;pmQd!z3nzWU%N_fCc2Ta&0a7Q_4rFMsuWy4r6SbuB&1Mf|7ZzVjbj*`|X{q$X zj+vdIzrE*YX3KJmRM=XZ>C&%i(7{~cEr_Z>pCWhw7lL@o=1EuO-QvXDc0SZ7R#bWG(G zC-6GL2f7k!zc-Dq_RQ4KRzQ50PV+*i42<@V?6zQw*dkp_;i_^^8{FRxw-6Gy z<%N7$AZLMh7ioN(cBk>r?jO97QE))z{nnS9V7sGQyrbK_KeEdU6_6YIKqDptO@0Jf z%n=VA;LGjdxWRqShA2CgX|Tx-6JI<0&a4S2t{{EkP)apXUaVTV-g{m8AQqr3E z%Ho*l0T2B>W!nK8!d=%0tX@v8xz0U7ieI|@vChV_V~Vl|c1Be4#%zJS6^B;4=&EA~Id! z%*-n}W|id5?3e)tvU4T2@Uee!pnBp>^uC&TLk`;s4=MkfG(K$omRqi-h+BYeL>ep7 zJR06||BtyEf(j9drcR?1yZRjnzSthIDiIVDdCI6XUEalLt>U(zV&j#$1&PkBGN;Gr zRq-3N*L_<3=K7?84-c5JGsXR&+Y%@ddjVSSeuRrkA)#s_GWmdHck%%de4POi%s=ks zO^dlIeH+ZxfL{3b!Jqqy6Z0g`toZ-K+*H0>`JOp^YiQ%ID>J!ChuZ9gA=Tb(7q3-+ zI{11=X1UMFHW%cn*%$*;m@;b#c4(p1(1P#T|SiXKb-;KBV=ap0-aLQ`;x#NiOLv)S!g=*cWXISWk-bd{&$q z;l0akpFS)EKpnbHfw^Y4dbs{?xzU~zfr2KV3HpF4Tl~uSNmps z@P}tcJsLj2R=n)-i?fTViK5V@r&DsC&YvRrBlXIwA9+F6#^eJ}-(*dH^t`M&io=5^ zA!%BXKV3?L1!w$3em3^PHJ~9vJFFpWw3!yW8RTE6}v3e8|!V}!!9S=>4 zZA2fa1Fq8#0AS52S)GkqQ=VoiW=xBeiW9VV@OxMv;p-|uH4Mgjcj@TNe2_C|m`dWO z0Xtb;b%lEWLwEt~6O3oDjnoLCb_LC^HO6<%x((4hIJGw}zQwbwPTIy!O}O4X%p0;+ z3bJe@m(*WXe@*)}?Rz>8?mVRP(9UI@hj%XTT+z9*^N0@f%%+Lnrn&@Ezl0bq8ALe#b=K2`X~)-O z%lxpt0Srq5XR$R*U6G8XR_IMWtU;5OvP)-KO89eGU3vC&zebtauRM~-q(Kc(NsrY` zl_G~_?K9fv1-3&OgzM;R3kj*Y)`71%3wf1p33PEDG4;Sr(I%d2P3#!&pG?B+^G4HE z?j-X(h&bp+%um-xIUm5ct!KZTXJKluOBoy`S8~7tw3=d9orU0+}tn=W;LmD@C{ueOke0&x5XbWmyN}FnsC~QTBE$=|dA{^zD_99~zzEk$V>><|6 z!f$)0V6h-BDxf01L6d?Aw2yv6^+EZwX&3k5W*4kGug4=)`|Cl5T8rZw9g3-BpGV=@ zD+ICkQiB0kVa3c|I?4l)`0zm&V$o75i2D9pt+qbd`kc>20;{~fZ>02^5ebeb>e+Kk zi%a*G4wXM%y~uAuh%c}X+?cBUob;x3q;;7XWZU`!w}O}(>*jDNabMG_?8t7;F643S zXaaM(8PM8M^lU!)*3bMl-|*M`x#t=IN8ax>?*Gs7z&FC;7f}o|QdTdqCWv+;?M!n`$uJmS4{4l5%h0?JM@>a6rj`AZ zY6Y`kgM_!P**k(3od2g|Pqb>rnHW0ZXZ%ghKO2}w@Mw-5mL>yFDf@z^yhcN0+{$`r zl8!-UH}Yn5byG!&CTuQ(-Yyu}#m1>*`&*UwJ!?Xu?0&<8`w zNX;?fc^E2sj;yZaLE#KSk2%MipQ2qce>hy54~U?0TRrYAMOe6Y4{~@rqVvxc~6_j2oWofW`-N>X4q~7lkDOcoFnpd}n{&QyWTRM8{toHs` zGL0fDd>(!Ri(a}X_kaVZ^N&=Y zODSB^K?{}7X$b|Q!?CiNyxLuXgDoH8Gb5b#-|E)1AAV6kmzr#Dy zVBzMd4a2$#HBE9{Q_S#?umOUx8zGlNgK$ujh(^Y2j`^x~D%a$$Kgt*-Lz>muRd_k@ zCj>ZR@A6QBDosmL&H4&kZ?s&E{IK7vJC6ntz%vKm_jf;7HcPk-&m zAn1nA4|bD=n)n4S>jAvd+8D7HdcMYV^#~5X*t**YNzv@s;bmmUyrAN;_7Zqa-i4{3 zKxm<71BQe>{=l(6QRZNmbDCsuMFXA{F6Ii!_B_(IN%1srb zMtil&kFd1^L)Y&joX_J*n!=*RaDMQ17tLTy#z1nozwa{PL`n|T^u zYf_OJqksXHRz!;sF1wula_vz4n(#J2w<4{k3o#hRjU>tYt2wwm^3=S6zaIFwT}SAZ z_xER-myS=Qx-oA}B^s_R7>Q$S*WSWcyaNTkf_=@!4h70B#nV7$$>TW^rp`Q~m9j0I z`|LMXvQR^{evrKrjw-{u)}n(Q?pEA#o6IX0DTa1*^5GV zBWQZ0xnUEM00dY_`yO-(kq<2IK6P5CmOr90L%J<2Qb6KCLey4E$5p;v`Hoe?d|jIs z-7n$F0f}!MsiDDbbUu(6ek41a3_3+9g~)-g*(e4s;__)h6RXC_OGrNW)j{U2P$;== z{Mx?joU?n8&;Leo)6!^5bO+ss2a7r3Pjx!vZH8E`hkpz#g3EUjh(#Do?v&))fQG5r z-M9e{niQ7-U9Nv7eB!A*(sG9d9S#RfU-Bf|Zb2qKcSMl6o?zJtYtKi(uH(3{CFx;hK!FkqCcl1y8Uj0(1NBD)%qFA_D$f>N!o&ZC61j<+O zuMC-mfrwSF_0beMqN||mdq+UaLLx=iU)cOXt>RSN5D@yd@l7#fg>lC)Ry-=op<+(8 zQzKnoED*w&&B?~HB68oI1((isUq6Y-yE2-wCV@9yl5~W3K~$dbcGu=5>*z{K*6Tvy z94DSGBq`T&g&E|cH>uwxFvVz$jheeNYfcng3#zu|9rT=+6Q6a7klO-+)Y{bGEd9u( zznkR46aZv?TYaZeyP5Xe1I1*ryp?e(V7b?Zd1DM?fXZ)yC;NrgLesf6Lm#Oo1693k zJPr#E)_wnIu)Dy_VzYem6_mCZVjxLMw9HE-|dT$;B1>{v zM1q|@oCqeYZ-2+SzU7F(1fRy(61o7xZkV!nYV#(3!L*kh$BKneT(u&;^8|bX!Fw^66 zl+WBr+r$y_{IOChk5tA*enJG#dapIK?K54!D8Ee!j5sNkzpDIoKKe2`Z|kNcFq%PV z^tUSYN3TB+(w`6!lu?$qq!1twT|fx#KF zN(*f9vWW;75Mr|3m?y87jMfunwg}@yIfpDcNjwn7n87N_R~mcQ`F*WyUSI$4P<*2I zvS!cCyfv4xmrkyO{Ug}$3CczyXRdAS8G}K`Z9rWH21eqSv@`ed)lMQ zpR*r_Y(kY^j~hUUEarR?I59lc;Q*(18h>uV{SJLmjlQGA!oT$EbSop?mMzEk5$Yv* zT0fk(pP6p5M<7BJ+eO9tQIQJ&+sAt)b=Kq4I$?d_j@2kVKpV$4r*>ZG5T{)X zI<}b^!|mzuq>6&ibk39kJViR{+^qW{zS0ipfg=x-d3=&n<#cK2A^-eT_)OP>0pI2) z8Y!MT8L>#`1K}kP=Kj7yPrrbj*AtxWJ?Y8iT(c)d?BY`-?Y#kdXX@&T+L8#C_Lly- z^6emVr&Pj00$}P6u0wyQt*ML@xzEWV5G61?epD{q(ReFr8X#_xu6%$E$(3<^P%}zz zq`0ZNVe?cc(1jnoN>9jsldTfQCmlFHBuNqP2Aly4&I^sj%!^u1{K~w+AiY3_L?S{W zWheFU<*!x$*LniIOkubpQOfH22`P5#e)LjrPGLP)1Zwyye|3eT+ax6MB!09<`P87L zjU{pet=0c}tl7}mE&2+D_2$G7i{(i-6w2+{x#;ic2!jD00O*PGm}F-&bd~!n$_0%xaa<~KFl6nsb-D!S3Tm{ zkJLdTkE*jR-j}J{Uh0@SlctYx_J~PrO%K1-b*ji`m~uwsdz z&C~9`J!`8tO_jrXdM0yr=VTe#_7c4;`^|tN_*!0pJVZb^jO~gNA3djU;X#gFj&GOZ z3p&{kW=X}FE(sZNd1_uPZ;r)tJ%XMAwVqc5o1YMRt=;Y0BHx#HwL;fA;Hw1PGnpq0;ivolh! zd`n?`>Ncp_Bc)1gZFvOoMDi`7o@6HK(*fKWf23>TMv-oYcd~+Tz{|#1)hN>v-zdaU z>KsBV@0i?I3fm|5S)b`O#c+wdeD^3wG=Iw~OHS=PU*^&T5GfpxuJe!7f4~k$*Xq{n zK7P|9%(TAAUC3>i0TP4j3Ow;K$VJF$Bh#m~qgVgDNg}<9y0QMstBb8wFuQ)RNDNxq znWlzBDE-`f9#t-$D;Vke4d{zlQ5z~+v}KDUcA%OqG&HPu<)o~vbmilau?D;KIv|i@ z4}@19S=joihK#sEWVM*3ianIq8YZRomDa;Gv>6P{fN4A+;?52=wxa^ClI)`b$*73n znxgqbSE?!as76p=LsVI1Kp@gF<6}@odpbuos9o7e^~w~u*gt@a2?ZBrW8MG*?qUbf z5N7Utun<*GqWKK7XckGpz!P*HWe&T|he#Y4I}hg=S)petJV1@1-$rksi1n^=KZuEO zC_LN?I0E=@mBen`CQ{3W34NreCWtk&-oD|QK{t!C`K_sP)_lq?cGl|-azcMhso~TR zdU}i^DoIecNhgh@8{5$V`GU4!WZ*$X=YvZ1E!97-zBd6B=6&W!0jGtLA8k87IL9eF z_wh1x7KA3aJ(7iEzY4#V${5^bj`o2V-*YW(F1u|HDxF%V-RUS7tJIQ6bn??NlWJ7R zy%go&5>Syt)7e+%6X>}IIWD%HyclhkBY@-=jE@%k#VMy~vc@+lq}L(yjuahqEhLrN zuUydv4WCH^))BNDKRwqfBz3|Zg(Zn;*@-|CSTe8rM)ECGtq5! zQ9O&Kn-j5GO9ZXDMFmZ+y^owOr^L9}DzH4eqxvOAqhSKI1?6=t>o^*Ro+F$Y?7(FX zpCFg$&v;3V?HvDnR~zHQC?GH7=d&6INMGXk7`($v;Ha2I>p+T&Jt{kIe2j$6D8UJy z99eXG`my=qVIGGJ5groHkWw_Lx(Rd9*yXta#|~1`IhufyZs|mC-?rATvoou)6_-Dn zr`?s+L7?Nbwi-Wa+|zt^>vPPD{W9|~)eoC6T&JwZ{$hLP?Fef>Z+J+rB9!h+nlr#? zPHBbt2?ODq#eU8du&$ITfkzu-(iBJQIbMJHa}ow2hEqmwa6* zjBaF1lVfx#x9zBLzS4S&?WyiEkxS$U;DfR_g4Q zUOZ*A8lQ+^=4b=RTNKqp*~ty7UX*e*y@Oyqy(6vf^-m(mZts&%W#tD8 zFLQ*p6(ZgZj*R2-E4T=qeLQkXP~uUhT%H)Ee$$Yq+VR|t#=kXZ>Gyf9<`Od?%XD-A z#TAT%#Cmy!VHmPV1?nDsR&>(euKgjEIjNDh_yM+Y<=wTfWapo7PKq((xqB*;4tf~< zB6xhNdh`+CXJNj9?uGieJ^Y}gQAeXlfX_e#-;-)` z>0v4k(GTBk`NMS!KeWk@hW5QCUr>Rx+hVXx zNB`2v=u}(Ky&8u?^qpL#qMzQNsC*)U(6Hd%J`KeC4^puK8)7Rai&DSXnY?>uQ{ABH@?>@-&uWg{lOj=`k$@W zx8B-Cr>2m+6GtutdvD z5Xf0)22mCMpE8*tGy%9vNbdcpbo$y!a@{k#t^CwCenZcP!wRtC!?OU3gSr5mAa$HH zHs(dcsknTBf(ek4THrC^>^ZMG15%-7Q+y%jCT-hHlV`V~NTct8Z>XJ|1Y%;_lXoNZ z>MZhTJt;1Rj^-`Px;KGsOb;ZLAx2#<^xTDp9StHAfUAuZ3lh}(ANpYwmclWdpmxUw zhLI`~$4$(@^Eehib^Rr+cZRZ1oeweKGykc=L?-LcfMw=ANe1( z62fidVP&0;(~n+lH)+}A1~bC}rIlms2-ctNi|1LBx)q%GTs=1Ve!sLdTHvR4?l#yD zC8ic&QA~~D4dCUTiOnD16HoyHdy|!%58YhTY?cJvNQgKh4zId&@DL_k45)Y7Es*G; z$<4zGgpzfhyIVR$7wOd@wdz&XKdru-^c#aDz0K;umihunKHEDME%N~l?>L1wUtt&k zjpKQX6bI28#)DA0EkVjL@iO46K6k)aV((`q$4SELd1p$#%J*z`u5qanYcTww$httgj9Q`hh zxtwr7++QmHFmVyN@R`|%N_UmMuZGs;Gs`sBDL<%uW%;V|HRWr|>&s6nPewQK>icRd z8Xsb&pNM$)uf6NJxHRXkRO(6ft=doPOP!_h=-heKscSKCREW%@PT?+W-mzn&R7n{0 zxsv6V#Z&W1MZ=e00%Z63f&-h(AF!hMuGK0_xZui^xi!p{W+7 zZ`Cxion(2_4ceVDfBcE9*t0X^M6ELZMYd;+fdah<#pP#C6imio--g1IY5QPy%BY)5 z6k;SN^)9)R8%JoJzyS$D7QVsXPH_=#Hq| z#QpubJrxwCG_W3E>|wdq08}y)>v2x-x(3O(gm#wkWw<|xcTc90?S&NGkfI1jrdfY^ z{nhn%*56bARQ>byf2-rnkh4ugXL0)!K$GF*6hrP=#*0$bO$r`1r7Vjj@hWCX3gMKP zRZBzVE9s;4aGOc=bjgjx zq@4YT^-FiOpKd*3Mh-HcZ!T?HF3QU`TzlD%L9s{-lA03wVWFms*oXCq-FZgX_J0AlQK57Hn(>A<(@JFdk!^O9O&o@+}Xia-sBJEw%-(6gbC;=55@RQ zximB}b(Fkc_>I}Qh$T+`r!#C4SAcfA6NJKZ(G%H@WoF?QX+TpFN;fxK)*wBucD^S7 zN#q(8(=vBM1nkr*U0b`-6(1+@hkJf3#T4Ev%QZgG^A}Z%#9vTP?)W5Zs z{857j?viIKY?~ww2PVmx5;&R~gxYP=tpi=bgS@qVRkmC)nfr#u4f6&<2kyi#f?k{R zc~1DN+);AeKJ||T0K&xRWKkHeI8l*Zx7bXFDSHHb+Lv=j74~l5x*?u5d8s`|5TNm# zI8{RPPV)C*BSIDvy-0@!-)iqYQ+rN*1VY3_^Ha^wHou#`6eux8G(wTw=bPODol&7o z1epFT^YjDFs84o^2m7NqvL=u53$`=R;F@5(!k%-;J-E(Dc;YrZav`>c+D96JKBlJ^Y z!Bz^R^F)tKA^?Ly6LikrePPo00n@u>R+L!LQ|cJ0m}M~F1BVxU!~k@8(d(zCpy`6r zNTPAf-3C3>*6Vy+@T*njb>cVJpK^0obHu)O!VXkJj~RlJSX9EvHU54+&o;bW)v9gj z*C+~Plg@(XJMy$BO}#L+Iy!~dj!-z~eAEP$jDC%|XGWGfXI2_tb2u+2@XTOSlb19K zOwvgGUFOdz#FFBO1T2%9ds)!huk1Xs^Gt@S>74M&6Udr~D;#EPy|ea>4AIwmID7<} zvx@T;)4DM6s>a|MQOLQU&ht>0!;DTjb76>m-k_{iucv--aR|jqHS5qV4t~&PYe7j$ zx0^SbgFNa3SQc)Sh!~o5fV*~!xR!@e zNXlNBq{@=!WNA>4=8fd3Lp4IJXwS2O`fvFBh{=KNp4e6NO6Cxpf#mnb|66ecEKY>~ zr^QR>1r0g~l1*YM7F|bLYTK)^%BmsnL;;?!4iViPME1!ciz`|f9GF1AF(^VB88aoe9q%>37tLCm0EX9hn-UA#jN0o)Xg}Rx9R>mJe zBOYYWKIu9gED0Qa`loiyOb^mr(qX!IH)Oi#wOPd5` zAT-)AzN%OHj2#ZM25k7mAyDlFyZ;5xu%TV9JQ3oR=CM{cG>86VfqshKD%*Mzj_?Dn{ejv{7vx^!qj& z*|BF&UOEZ>o#Mtvz@!&Aghw$r9uT?uzu-D1Ovh{TFvX(?C)qqSHh#K89Sxynx#MuH zc2{&RMO%_ncJbcKgv!O)`oe|RP7sa4+@C7iDQMb<$3#qPyt!gkE+R9kQ{{|3R9zP& zv15b=rlF-Nd&+Z%9O5x;x89eseuU5V%dDLW)EZ|p%BfK!rvSq4?q5?p2(m--K6NKx z7toMXBLjJ>aAY2$nA7xFZ32lreJ2aShJ(nBfS8aonFWUH0xlb5(> z)yU+)%xFLCiUq$iQ*8Sf&;g;XE`^t>@LiUYCSL5LnjK8d?0|)1DXg`g*jm@RzI8*3 z>Tr&ly0|3ad$js+U?FLEKSF0GR=S6h>9nc`i-`SNOlrh+2#A9_Q6(n7$fd#a7%vAe zlY^)}th9C5XPr4TxN?%1Yyc4Ma)DBLMWCx}oo0znA>lnr`lPcshh*dLK!z+>Ov< z;60p@6kI-(QA*@8*$KH!Wau>)bYPS)+RuG&^mMcSpO=8vU0xkNB8!v1ukLaD&$9FS zyEHHj$w4D2Yk?_TslA?iMnnhLYIRFfk9ZCfr%qnfKV)b1Hsa&$^A>f84P6sRX^HgH zQwi=%MwzPXPENeysj@9)LGXaD6!;#D$)w@W}eJl_Bs^?N*6!4b=To zl5&Me#MsQo+B0Eu))?|<6X+bKpv8@{t=-Cd8#iZ-TZ)`gwf@}3!y2m_Ypo);>U{1f zI(*K3ROWn&I`w!b;WyQKeX4Oq;}KTu=``jbaJ~H4^5e=+EUzlBZBQelm&X0WZ%9`4 zcT2Z(FiisAI%G{^?Jqb+ps{5xW*=?R^kH1Zq*f#_muF{1pd6)UJvN2)fXG6b(^lh! zxF)E-)qqlghm4Eh18L=hH{5 zc4gVhn1z}$9TpMzrSc;Ol0-7JWpP|q(FF}$v2M&|#*G(lC;+4(@VWYi#v7ZTZ{E`Z zL6(lo&v$Wtb!~=Vwi0_UdRvsvcZcvr67Bx!tFF50G5VSaWiWYMp`K?(_?V_>r=)mp zJo(hD)}hlG7sw5j=Y{+Tdvt6kO#Q8_gRV9A4gcAUs+0fulwGd4LjEJx;RW}<%MzsS zGd+g~x{hL_w6b00BK=45X;L8v_wR-r<ILAnSp=j-~CF4l_OXph`x>+3nzS{0sEU z@U9>uKHI}cFl3rtaQ%^l!9Ex&2q@;5-@E>`kBW32G(wO4kI!m*^`Bbp#*XIy&|d{@ zeeHB~A3yp6Cco=os+|b??gIXv;|~dv(lO`Mm4*wS{=i;$cjzi`!6F5-o+nnhL!z{E z(0Mwl;sKEXhi>8?hTr)RRP6K#tdo4PRS072u@CgC4Hfa-VNwd+T@Xxb1;=02o)4B-K96c{O`h4ojm!ZlhjTh?mD$g5{q zn&VaUP-3#_m6&qhGB1xNiZEShqPS>k*U0d60cF5mQCJW@>_V@7Im;xnk`4}7SG=ua z$hUhPu9M%U`s0+8)9LwGb^(62Y>bhw?$9pjaFmRGjn$(r5JVu5nxnTH|L^t#Ir2>> zVNevV@=1;nYy(iG($eY<##}mq!rBzrkd|id#db&6sC8cMluHdXtJQg#%xn31k0?uw z^mAl+iNa-khg(J%xS-Dtf7sT^evw0NK9xvUD%9F2g4;4G_ABiKQYv%Md;PnR+wjJ@xlVX)(xy+R-6 zUyd?RjS=}jd}Zs95ZJtYcm7pSn@TcRRfZhOl>L`i1M5DWGRp_(1Bn`%V$ilC^w_M< zKX*Pw{TJGp0efRuBbR+C81LtHxsuXgq4R;GXKg6mzt_jK!r+p(2`bv0x@Lz2Mm4$B@BFb z;DHJmHjE2b2+LpoYB>P9r;St5>IQ5+=JkE`->pB#X8*)i_{ao7h;wC7rBn5f6MF%Z zVAg02Jr&JwqC^%8MnAuxI4J(=!Y|*Bwx^{BRtMbQhISWq!hRqb*;>IMIxUf~ z2ny(gauRlrcpTcYqo0%4&nZ(>!kccL8QY*5saW6U$D5zjIKXS!zsa7!0n;GrHt1ps z+M(dE(ppNQLTXpGaxgdZ3=X#R@$r>zXOuJvh|`wd5!CQe68O_?{9LX7q|sg@jFI{()nHM$W3cTo{lY|C3x-{y+pOnD@ONFrmqLRzh|IDTG3v^(mwwY?VX2Q z$u?UZI11)>FfssQ`1pk1G3rYN=@ckHVe?MYT-ei7;pM01Pvp0kM3QLpn3|31C8#)@ zKPv@UgKZ9Li|W{U-Xwlg3P|!k*}{NPbiGZo6ERNss`kxfI~g9;ici^Ycwic_uVf-x zT5<9o!dJvm4#o*3!w4tKHwIRJ((lVbr%?~;KtyuvXHViFVhs~>Ac9o=$;0(v z_ZgO!)6IvC${Dpsd2;oBflST=P#NXFRhW!(Z+inK7v>Y*Ej=LQwYzLR^&p_GykYG@e4aZdbGC2@c|=5((f z51g9831$O6Wy1{{Y1YeY5A_|Fq-h8k;i!nxHPN`@Af*@JcbU5^AFrKv!sbJeDIP2F3uj`Kp^znQ|G^uj zmN!rIQw|Y_hh`5iEf0ueT)(98+I%#)9(TfnoUh2P${xwk;F;`$*;h)>EDe^1OJ6R1 zrS$Kmufl2mbYub53$FHewSTRBr1o$1C)5u#&TQP$Tuy=M!<$z$AKhHhT-&_1`Q+xt z=9cEuo6l%IyZJlK{^m|N3!iF!n(0iRr+VXy%xL;@^Q+8h`p@RKo8M`Emy(j71a-A} zZ}U*|aI4y?wdzzHHOaM})w-hfD9TJ83v+5iYa{HbKWe?Ab$9FETVHK&U|{Gw+Fxpa z9cQdVSNqF5SBd@GxvTT{oqz4z-T83mqbBr!%~)V>d`~1FMqe^a@d+qPFrgxqCqY>0 zUba(2JL@H-_x@LQx^W(lB}Bo;Hwk26_tuFYldks=R)I~qBVu_d4Ye+UktUn2age_E zdaRE;x&BcFRa0{E*f*LcLVVPzTsbq9SS#fz&|l@W5m>Mue&je&VsVGza>-J-OcJuv zpVU4JiL zizh!ssUtV*Gy8Vr)`bUm3A=OOhW^oBKsz#)NPC{|01Wn@O4VAP$3Qjav6|XY++%=?f)4QSWd;R zUcwgXemNwz0zeCtinRa;b0-}3Yb!0JQkbuE5Gi-;JlaRS0rVcVA2X(UsZGfOg&|K_ zY^0p-MWVMY4QjYff^etk$>;}gFPI>aaIp*88SPBix|%P-T{_txXSY|H)tj6D)%@?) z*{$T|{Ok$8v`1p}*oG@ka1CjHF4XDQ}bX7VD?{nj~@V6pMkLaT_p_ zSG77_y`}p6>T43Zf0C&L{7_}?S~>+B2Em_4J$TodG@9?E4Hrb+h&_|P$ihs5;y|Dvf7rzXJkvA@Uh)VErO2i z05B43iRh0BXDlictg$#Smwb3CQTUOa$}&&x1Dw(-r;x`Hyn#(+kD|>`4m9af0vUg70^Y>;#`DC?DdwAt;JdaLH27 z^VAeiCz7JwzEtW13t~w>?@cZxLDwwMGqM&oUOYOhk86X8pwJB-pFg!6exLo~2 zz8&u3&3+W0z*3AIDn5x>MGHrU^Cg-WL0lM9-Y_9AVMIMcL3tpGOoE^${EpxP z`^k@#soyt`Y7)&+=JvArd%EuRS!)j=OOkwRm;uFf9OOGw3~QN^K49 zCS9vY>g>YTD6%tL#Zu0+Ia)?~OOCz$MY5zg8A$9!KG4D}WHxR37A;$J zZazJF?F{^E#9+w%fAtHx5}!sAn4}{jn1krrNv1_CCT<eM^jYSVBCmyG=f(^h#cX5M*yBIUaD$?$#C&gkZ>YUxV)p8rj3e-i;Pq!I*b-EZF zmdSl!Tzbo&b}^469P==b)K*TI2k$`71F^})EakTcPlw=Qa4d&#S%X`%W(1^ug`98I zJ0hI7KR^{8M5knAO>l6qXz$Rw)HpzD zRoxewfySund@gswY7bot=M3eg%;0@b%@(Va023^5z}eicAte3sls%mOeV7f;$W0PmEvJu{qpJ8WrL4h-2pN>G!R9J!P8 zt~GhLLPfE*>fAK(Rs;J- zKaN;2e+Q{UpZB3hPWH9q56o(l zJ9kLM9D7lAv463J@AAy?!xOKJDryXBT&Zp|yGIGU>v7VC7NT;UB8{!ZfGBWLa3K<{ zSeM7o71?lQPRf?>q*7sZU=oQ#JFO5>UOZW6g6ZZUwVwGv@+cDLjf4ZQxB7x$h2%h!q0Y!pc5I2=v%-hZ z>vEuNoHF2&h#XV2;8K`_%E=>|@@KF@^PEfJo5Gy{+#Va;KDm?g0yV1b zByJ#frLRkEPNGyhyR7v z&{9(FEe<8McZ8`VTn)C)vxztieBq>j5L0t49SXIQ+BjX1Et6Ib2Ui~)`9QY3KLI27 z!UcDg$AyZ$6vF5P2%fUMWcD4$wf3}rH(PRxC|}#hc1Rd>o!KAiLB=$XA<}1pLG=eZ zFxAJP~kNn--&CH@SpEn`0zUmw5D$vcQU?vi<&#?h#dYL{g;4@=_o2|t~X<|m*ejUpj+d;1$%3wU0+{f<@)vXwC35QZoO2tG_PEtiv;uEom}KrX1^@`s{F=ElXiWN z0($#h=Z$_ZOf`-8kP88k17bLDMiy>6I+k&ZvP};EnF?4GLMFU7T2 zYtz;bYsW!BCMg?Bq{PEmIF>0b?!twYBY_h+NmT3bu(X%GeT}u_>anRlH*m08cs;Gl zY3dB0lm{A@E9EEO0K-;$bo`w@RjbwRn_ThyM%<5L{}=~>aqnFKif04ZA-~>D@>fcC z;{rY>jr7_|sHf%S(4G=36<#1XmE08Wz8t3<@$HtqfcUB~G)Zs|8%Fon<5DRlopSQO zERoNdmoZu%Ag+(Z*l%&~qJaBTrO*3Nt{*V(H4O0)h{x)v=agwEOILpAQ2j!5^iUlq z{KXuR6LQXoqUQRFd8<7*+O&+hfkC*irP~|*?G?rY(l9*4q1=2ylh}xbk*m>%#)_ZQ zX(AAy=v!=!dn#j%DYM0f#rA8?MDuU5^V9)NE>iAkVCUwKFmZ)boL4!CAp>-D**Us- zk_=r>$FBUNo_<|jzvN1~J=wS{7<#UWExbKy(8=cQ0cMw-3^KL?9y&A_&EmH8PxOt- z$zY8^YS|72)jhU18g_0e*wA5OtBpIF=QkhRyaxIz;JQ2uoi+t(Z-T&zygGE^ z(_=MDnk7$76x}t`y6JOjn{rc(N8^bPzal%slqn9#x}M~R-i8|D2FXs{hi$60wzQs- zW;w|?T+biGsPKty{a)+$VY|H8Mt7rI{<6gUDxdc&77r~t!#vO|>`ZO9tF+?vyC@$# z2%Z1!V>@phNu$@bK0eg1jT7j3LpgpAvbkiy=061(B4xiSfFx4l%-7O;A9`VSD$52x zV*SL59I!=185BD{G5w^z&71P31(L|lAqp!^sf4gPJ}^#8&EaufX6|~t5Q>K=RVD6F zDq7ts`TUJh5ZAvWYU*fJzGO#qi@=ga@94wlWv9(7BqxS@)3}^s6e&-*o2r$jp#kg9 zAV7>NYAZDes7u@}PKb!L0hLYjfp^<;lQ< zPiLl^5Er}{SngV70wL+S^}OHS&135aV!GqUd6rNqy55o3#PtNwMlnjN8l-=mwzh8u zeg&CMOki?abmhbUz+_h*YAY(A=#hxPYT}5rm1K$ccHj?4s&^>>*)CgLYfT!f;lf0V z#7mqY$l2?asQNqEIbMxT zuAx|4_A;x+Dm zszu#@4NO_&N}(YBM1-0WM;BanH1nDQSKK6IgA&Rm`mQ3h9Rj}vjeOS6kOsEq>#kF% ziE?}0me~ho-VNAHrgH>BCSR=RQ?U>JE%}y+Ns_4^QAKXX@eGjCE@E$_asl-*gL}-IiWmzOBz1MmD$vNUn zjm_Z7?G8K0De`n6$={LB)1b+Cn=1M!jhO5ojT6rw553tKZx@O0bq7J@mnYIx;Eb?j zNbUQyen?trXiSuZi2NM{NkVCD3*kdU*hB1|5{A>>ra>t^6Rk~k208ochZ^lDq7pZH z@27}G=lI?e3WzN)E+7_`Ba9oj*)rFCBn=7GDGiHZ~FIrZ5s>I-y%4Y za?7o|yn0D3NRp#Zlm`$S)*KJg4tMH&Y{sR;eD$t@i9*%ilARkC1O9UkFclkUs|S%q zG?wpZ=nj~$I(AI#atR;?s8Fj?!TNf+{JrLTeG*pV>yPi0Bc|QH@3<<@4fOHV6j`!{T|nn9n9+)thsNOPO!v%pkTg9% ztBy1I*&64^&BNIuE7JsH6icACgL1CJ_Ek5xU&zlwzm^;O8?#wkDb3BGeR?Ry>PfRk zHbT^e&_lkPM#d(36~Zw0Ca#lH=yy=(bE<;v-2|EJc2BQ|^Atk?VM#+NQ5`_0n|WHl z)q|-~KLbQ}cXmPgcGn0k{C-W}2b(>cZ)32@d#BzJ<=SN93W`_vj7$vS68dD7?kmj! zRrgH$<{e>W3Y1Qy4@J!;W40@V#&a(y_qYALdEJas7}wb$6yVAwl+yRi{Gvs|s| z-Yn@(V;ky_pcW;1qGsuXrGL_}`_jisA1{5Tgr1wmmyLebn0bi{3;=mYxgR8^i6oO^ zBR*xvU0!Gjt-QPQ?+OCp1)~l^*Ep>a>%S;_ErH!PYu}|4=c&{)Us!)M>{s}%7DwMR zv8&XHf*XH>2pWYw$u^3iOp@D&)T}_KE{^_rg0KR>=|%U@>bt>E1?%t**o_1>g=G*H zdf;lhMx>fdynILB=+5wH#5H{Z0dc2Ddmm^~9calj%TmV3l=4E5P zkhPGGQ7J0Lij~@Vwey*JQQJdncpm3y!|;MBppp3CHy;jP1v1T65C%_E_j7ngqGWJQ zZz*}D{Zd$YAGJ2=4m8+^qhrb~BQ+YF`4Q_wx-r!G{R%DW!ROe5y1Hw%rWK8X80F!> z(f<_N+kuk{J&}J})VGnrlzY;8pCJg`)AEel=k&_&zQfD0=l6PAlHXvaytaQ`RGjE?l4~z` zWW%+knv!6dolzqJjQ|^)!dX*H$32Lew9jg74E1#M`E4F3TErwzf;x;Nf z^K@y6Ydc2;Izye|&YL=K?!2e-ciFkP)p;Ls z1OMx}N`bM`vC;j%W@y(vkfXBg8yB6s=)sE~mn{PD7@v%Z&>VHR96~LxC88ZwREvs| zmxac9b=KCob!@;&9>p0CBu1`nHzwq($N$8|2s!c@Gj8}?HQ&4s0qO9_&Kc~mH$~^! zcI0gRjS4~f)}7=lO3f)>12bS3Zh(SU*SPE1W{bDb=m?Ro_+tuj+RSx7@F07&3dA#|Y>#n7+6r2faC7xpw%`L76jmig>#(fY0< z6_0P`cBgndOBDTj`0853J^a|H)XLqgSP)%o6OWYlbJv2t$v}%rAjh~Xo|MM5C2zZ3 z=`8nU6ViC%x46KZlP1IxXk{HTupwhkL3$=+Uq*E~I%IHO#u=v`c?{-WYIuTI%=0BJ zJ~YkQd)+40OCbW@RB+|IFQ=9&rF!*$>My15?knlM`&abdeRutH(R;V`!PdXDK4o

!3mDL))5_0{Z42!F);E_P`2Fy`|xN^#T7-uJ#%IS1NTeE3f2~6UtaX ze3R}cjTiSSxtBi%q&R`Y#VXy3D}0S?p{+?nj9jHar(XD@q&E>G5mRTm^gYz*$#J1b zF|`TAtC$l-EGHzKr=3>~+$%gHqfj*2sU^;jr13vyzNhMBqTWPwFU@V?lX6`*;B4f( z#q*_ij~W{j?7?F;=g2kIG4EoW-><1=Uf>w89?C$X^x&+8d^@^jmUP8!~RyHL<4)10G^lexO|_`Q8e+-$5DN30Z1>UWBwDE=hwO3077~sy7<>^eGbH9gD0j1JmWTfFI_FuTI zAj>(8e;;xfOfis%XmQnf*?+*PEhi=A+^?f%bz02xGYdq&M&m7CCfj0NJ)zxGkH>2< z`l70YIi6CAt4xk8Hlc^%GzdsSqjcyn_4 zRje!QGEF*)kb5f~_rz~m2$R3{#r27~d*H}$^U_^A{t;A7;LR>&6bZ1>Gu3fo{+oWu z@m)n_`>}Gpo}KmbkD^vXxIY^7m2EfoM<^TN2JV5MkFW3>wTwpp3%O3y1Ts1pN6Ij5 zZ#0S;NBG_1-^r%1yFgD0|D64B{uBN|x^o4BRy)RZ7 z5G{`^sD%lDL8uBn_aWI3ENBINDPGB+$QBdIDZPU`a{iG(?q$C`;0?*hHj_s;Bf;=` z523AIZb&ZrVKb6T^20~ubq8ulWU4MJoOP#VB5Uvn%}mfrPJ%RwPK;HO#mj@Ly6Klm zT~0+lI-t86)N#}`4}NNk+`&aRFW)3r@G7}|O>#~0>(@w)o}k5=cfZ-VqKA32aj0qk za_FeoE^cl?l16Oq;$^BF%)!pgZwwIJSTY?{t8D2r{3tj?uV^8H*CRPoc>HL zQ8n>oXB=?c{ldGF1b^oyHK09gEI{>;$>$yw_ZBT?KR%naBlRl$UpdOU$f)lDg?AwYYfJIHs-fM z4j2zxpEy-| z(Xm;Y+G@jEbmrOW`!uOU(LZf*s=>H>M+p7YW6qPAb)#c+-Z_Ck-tslFe*0*(IMGRF zhlr9Czl^b5GR@_`m(ggBrgMf*KQ+PPzyKma)TVhdGyJmb?(RXBpb0$Pcr#K@V~yvy zPBuH+hg$hOZ0om{S{bxJ`k>QmiiKp&?{MiCWmk7k2TGQdg0ht-HdyEw>4#iza2Vt;Z{$f`3JPGT0s~0T5+`AiZrA(xQy*0*4QI0Qh5Tn>2zI^B z!7?wWif)feXP7k^+aF3~8HFb97i)K~hW%=1NQrz6lJP;7QrRDRRcK@aSJYH|>P7Tc zZJFyslxX*M=)7TizXbZ_TXG@D(Wfm*jA?N;UC3WT-%`i^NgdmP0BD!U36f~}7C>DO zG>Gk`J4(pp6A~HVtoA5<;LHJeIGGwg6vLFGU?-jDV+6G*<%|+~VYgvbV!HT3f3a2r zRA(rZ?mLplpARGecpkZx66qK<_=j}GCo>nN42EjdwOa(s>P~zE?;H9L;4rOpVC+F^ z1~t$)x(X9o=arrMIXMWK1EC?#o5ek3Qma)haG`dkLVlQRpQk(ZZh3;D<$q!Rs?W&* z+B!$M?@Yz*@2;NZlaYZsX_Lpl`uqp_5^;!l>Iey9b!c_OP+sse(rVG8Q9YBKxEMt~ zV@3XBa$ES#TF{J-qK1QyehDKwVmo_-c#a*?3w8=?KT=u{JN9CRe`i>4hGaM@5vAr2 zQH>Gw(Ph3^%ZH^ufd3sC4qr+vp@RYkO`XLLxsLh!B3Pv^)UM&3@sY^fH3v{H{N-b!N(OgD|^pXzk^F}Vww<~k8n%6u*< z$8Ggq&fXdH5#a>WlZ4RVd$%7WE5?#YhnEoNfV0DN z>PnacdujS+%+APezsp))G2W1Hj%(_3?$juvz#z7K4Rq~?H@l3J9V39QeoNl_t&QUqtU3(BL(C&}#N<9GHVt>hNZqE6$Tg!p%k$ukvD!C{}Fi|JfnJqq^Ye^w&(=J< zA=sP{@VUbDrWO#LS!D*ZAh=#1p?_1}4eXcYW-E9T)h@{<8V+Ofj&GHp!V20@Gz=y( zcs3{2oS!=X=(&OPGM1P=xT_k%5r`iV1f|LsWD6&j^jSCVt~e@^ zZqr?2wL~J>90*!!!uLH$Ha`*Ok572PPrpaD<4)2hACtM0a5P(x>kpd8e<)<=by%-p z1Y+0*=rKSjX8PmOX(9|U1W=b!4Jom$WON8BbJrU%W3WqKt?Me;aL|X;C*9hNUNg0d za@PPzdlJ+2-{5llxb1w@?Pulo{ivih`cSpDdKM=xwmJ^SI0ybNy%rvAYLQuyJEe4q z`h+W#b(5eX3QK6T4UUx&FNI*EEe5-Le1y7kkw0Rm+~4|epJ>aE;GoP8<70r=wc0$p zly7Cdbf9GlapZ;pGris?!YK0d1PXdY6 z9QU@R)8uReRn+2S0m{oKh)GIY^REvSTc4_71thEoJpZKyzyG=M`ulIU_=^xVf3$~?>7v_{^T@n_I)@^oz-W$GnJrEeXq^~-al z%(a6tV##(5Mx_3hd3ZZHKkp1rX)*|MPXPE-*+9WLux9%+N@g&c{i8J3ky z5j~FxG`J&K+zZ7gZ-zbCS7vVUrtaM+gfwt$0M;QFxugNJCQ&T^KX5I^7n+<`)8?%F zK-%Pwywd984Il*j;P4RGBSA=Lu?FKQod9?7O04g!f&S_-dP{MX--RUy-->in_nOmq z$!XPyfM*N`#dL#wd7-9%1E~j9i{Gc2V14kgLJoK*kd4Qrv+IZ+K8xn4{t)Qr9@Yy2 zLUCowM+z?bv;P=E#ONKSFK+r`M1Dk|fm7DQ=tmo}B6}XGR$a9W1WQE)%2FgFLm?9$ zKvibmjs1UqOkTFLJi$yw&Ix3bOZqv#NzU$tSzA3G0x+|iVHLxbDEl;W1xN5m`ZfY2 z#j%5yl%Jq4j4#HP#H#R|DPy7>!WdI{$IHWfm}n} z6{xCF82qMcMFq#wQAF~Mdc4ET9;BH>J20D8Kqt$~Pydx%PWA!# zRulig`y$)sQ__)5l;x;a4B5GP>r1C7{s_w7a4YHM_yqpj-o**|ttdBp^wwg4DR^*= zq0$vPSTlAyPPVc#v_5;GyeB(kJp`K9GFO&0Og|3q-<5yT#ZjbC19;guK7RHBxy=BW z(%_0HQm&2TF;s$!NHd57f>136G=5L9;>PpUqnvrETn^BJ793F8e2n*8I>mq>MuDY*o#R%q~7a`EmeLq?Kfk5BD%JrX}451=gv z5mQXraF(X(o%wCKq zX+ZtY8tpnb-bS6ANsQ2$ns9nJGCR*8_gsAb?QnIoC&uhf67116SMQ@*^6f8zI6CvdYJp zaICF+Y`Jd`QR|e_`g||Al>Vn(U?uZQx5=AVGGT?1 zRz~;_1J)rsdFj7t^AsNGAOI5+9o{3itPrZ9XXh2)C{Tk(xcp`LRj;xd2*x+<>uG!Z zBdt!VpD*T2s|kKf#FF#RE)OQVG7jiqwrn;`ZEZ70>Ud4D8Goh1=5P%<3r3;~_wf(N z%QS?8qz7b>jMZ+;{HNuz&VAeSn6igl2j!d|Fd-7RB!GOUoR5URhsRJq1w4ClO!+mr z7Z8MR%e|(mgi>j11C)Z?2lXK+#QNG4dO9dVaYJXZevDBKPM-{{9cjGfUfI=#bDeOY zL<$dr!3vx1&N5@FQvPQKS43ID=C9kfjI6h9m5MJG;BKYA4~^`Ef%xx4Z7lCF)REYF zxbP0SPoul{qdW_u{PEPmpPSFOK|*aibgpbcb_Za9yW)&aEB;THZ}M$CF1Iho_u`2yG}{gUb=D*0eyBxS+o ztDYJC&=+;ZYa9Jp$D4mlu5wvTIJeMgAOfuT8c+O-lzV!1yTFfaWspxq8yKxs3a3T2)px(6}cQ?g|+h0o{%eI+Bs$E@OL1owE2&c6cC7;4g>h&$y9?tHwenDcqe zaQ6R{jabd09nbtzdmsMxG3;OdD7SRgu0UoBI;|g`^{i`=GW1)Dv9$!T?cP zB?V9aPkE6l4rImusyq{JrP=r9u15B`b;)L`1;tt-EF(d|Qxuq#a()~o$TZ=I`fRC` znI^4C8oc}&ISaz-p5ZYj_;jT14KkwES4-y@y!lXa%lFR+*kg18nHOHD!C@?pvzxn4 zZgCm>V-%6lRo)@tYS-gn27K8m*nY!Hz2=M z5G_3OggoYk%tAaXkDj-l<_DfVO$NM`KI2spo=l^yYksJ?b0KP>r_<@ol z;eKn=030Y=#?J!zUmWNWw++K z6t76RHn;NidC=)2>zlROGG*+7MqH6&XT(9UlKPCx)Pva#MV=5!Z5@f zO8oDbb|XgmEeP%{k59Dw8{wH*GPo^L&cZ*#VUS@r)d>4F zK#cZivvsE57Wh7YR3-d&bPE9)2bJK`zT11`t%-vQ634ctL(;Ry;{Fo8+2&443$t^*)b0<3bSq1okIt%+`=Q;?|oVO(eD^TUo zy~HmG9@P|xL3t+4Qj08ZP|jnc?a~u+6U=)cN~OTs7$!as!cG-g8Uv2&%eE#iN;D>$ zE!{5<9z7^TneR9Fd5aWHIE$Ln(~~=80kIbBklrg>phM04pKeT*6^=}p~P|w zLIA6FmmXv4Mcvi8Kjz+L)vUZpUm@>;i$$vFt*7a{dETAD@%Jc7Df`u$d1mS87;1kc zSSJ4fRi!?r)OGq+dF6_EP6OH2(@Otvk>zv{s0}X&lAP|-0%;Gr1W_K!^;84YI))L0 z0sz_W(fdeLYHIOxc>->eG$}b;K83xj&t#D15C3NBI+lJa4Z@sI4Ao1w0F3aOx>^*K ze!r%S-ZiVhYhceP7GC4C4Cu<1eorpz7#SGn6p{?cqce-YCAV46cw9~CS*$KMZWn3x zi*gup2pu(Ig&=@8UHpJulSs&FLLZ3NO7sm06BJG4SxtROb^(OT^&Adif_xzwo0o$+ z9G3m?qeW<6ZqEI%*G4*2e!u6)l{`d{a33!ezc9c5hyc1a*~n2uA1I>ux!%&BMouC# z62!t`I5~Eiqh{sKZT4Mq0G&BIO1`N+>{~_8W;=&Lf49caV?(#I;(7jj*S4AG;@lZg z-(Ic_OpX@SOXnn`Vb7PH)+LG>KO0lLK(=dtu1dm5&h9+97G^>i)uMnU6UIDIQZla~ z>?S!A@perA>ci8Qep>FNn5uXW^)~RPT6v(Jhfj_mEIRh#wu?LxQIHWDNERxJ?*G+Ao`P@{QE$(7>G~kbLqzMlYDlDf+OZ34E0>DW>)02#KtJ2 zK9}Rn{D<5gR|sv2!PH|QZ|*XL@2U4=Lf8!`9sUzHt>nwxt2zj?qAzfd{|w99-?9zP zmCZ7`a2}V+Ef(D2ZhgXVm$>%UfZ!%TU#fs}2Vt&bnrb4qajs^)+iA@)5s%z~o#S^F z#jM&7)K0p{tp4pzxw#v{pXU5hh=69a^k|?Ul~zKwT^muETZWj{wmj+h# z6Z{+580|*W%W02lBxNNTM+aNS4VGG3mbWSCaTY-&dD2_wU#OCia^oy}!B0lQz$Tqx zK87M719q8Oe~&LhUs21uijjrM@?c@SY>BYu2jwitbVG2L#ko0`jW^5n9jF|VPQs9& zcOD|RRStBG0c=)dc#7PF>TCq1xDAOyGDADJhe=$rsfBx_4+_6I(j=Z(sO@{Y$-nhE z1fXws=}2ibpRkYer-DynF+GU*>^jo*_7>}hu?5LOb$*riN+DUU{U9vKa0O}~0bJL> zcWmxNgO4=gztKkvGI^j<_qCP0jWec!f!K32wh&NgZH04-R_<^caghm{A6TM*FUF){4d*!-q>pBxZyNmg_Y{)$Z-O)x4S#xu;vGG@Q z?JSPhb6l7d<`|eHuwr8D&*;Q)m7{u0|0}ywjob z@Faqw=y_nW5-A=EX11c71zZT1|RZi*k}CfoR+r!q77f=^d6k z^1M93-@??K4wCg`X;qy+dfxg9BLoE}yh8myHZuY1YqCBwT?-P;o$wrp`My006FRGP zZnH&XP1v```F-cMm_^(&kT6T(f)*%ve9lH!9TdJr&dml~@<-(QxS@*CE46;JoY{{U z&xoQf&!LFfzCETlHavzIx!A8Ncd|?P-CdB}->2o8L^K2(lOCN!ZnIX!{~oW_4%;h# zy)C+DvJ7d%Zf;()*GXXoy)(Y?swgRvb&gze00ID&ViQNy;k`Tnk>*VGM_zb>;W$u} zvZ_~Jf9J}*d(4#S92Y_ShZZ;hY#A zTr6p`&meL#2h|w_R$g~0(^6s+^aa&=nHt3rU`=8~O}Gyq(N^f3{mH^h)Z`1aSGqrH zwU))76SlQoTVViR@K{h_FMTX!*X$UZnV5Ai9z3z*Q854DMurMJq`n|&+;MrJr|ltp zGC7(EAjstIEgpq112)+Q50^ef^O)3FnQ&B}%ZF$Z`OZ%LqP!gi=a}%;W7+YUhgL>% zDK9sMXBFt%4&=-J1!E@8voN3(jYy!EU%4Sle5SvNyt(<&&`J(Gf6YS=j+~USBLNpA zOezUG=xrU!J5@wnX`1K_}Bn zg`o;4G^}CJpG{F1RAs{))(WMg<5+Gf@wWl$g!a1$w;z*tG@kXEt!pdH8k8wD>0wrV zbaTy_*KG-VvXidT=La@~j$?DOE($i}`}dS;!zDWh&rtohen&U1Kh$u(oULxHxi~C+ zNv;4?iePSNDY2}inm&^jQ^K4cmu+p{eH*$(de{^hT~8Sbm#&t~6V0CHU$51Y$BGJx zxJXyi@aDcOcONX*of^y`LM!_iqlQqrcCcI>0(0Wl=s$dhe|En3hcM1Uw<-4n>;tX^`C{jKTbU>?Nn*AfWFy6xK2#ZT{efCV;U$V{Tza=-Wu!tOtV(C}pN{yn~ zZcoO)KTlZgt-e~WC4ueKEMO}&9F!I|+ynn9R#8caD9J7d*@`{YjK2t)KDYFgla?<|etdU>$XFUw|<;`F+?3#ZB-H>U2lKbt%$L`qMBDZ%ps z%3+pCwPULvE}%9{E-|9msE%zbO&p&l74u%LqD?-K)N`v>i99>TXo* z;O6_Xi~Jh7ocD9(105zv=$w9Ylu*5h(R0>*=T4UkO;O7G@eH{%>d*Ei_4Nzc01+pU z17OH3lJ`ZX17j&mzb2Pj$z+nxdQ1G@N?)Az{Bel_825nqz^e$tMfxV@V(NaE@**Lz z(f#oCH@JV{K6wc^6X&Xo$>FNsLQ1v~76kIaACXGGbSvE4NePK4cw*=e8q5tF7fLDmTH^4^fz+Vj@_L-n>XRelD9kzirOoeTdT%R_DRc*-5pr@up=1> z3Kw>^UoP3P`#|HK+HJ5cn;JLS<>s@wag#l=*(}YO*vl1Ea(JwqDOX^2pra1x@rUbH zKqzQ&o7=R_D{k6uc^Qc408$263S`XHuK)Bqz` zt3E`0)cCF!z!We6B^S$A%Xol~XvJ6v7%`Cu^*e8aNjPth2Jlex8tKe$$z$HXq#I%= zGL&Xr3ep=Iy(to{M1{QO2cCMRytchNC{6WTE$~mJYGeW?$qDAD%IxWLvb=j`Bs@>g zJUr=Da{p|e;|HPDFOgX|bQQ&8tj1uny}^U>5$>US zhI3L_^6MR zu9@Ml2|-H1d9~q=7N2-RcV*$-NaqX*14K43HYOMoRb&;o=AV*2b+e7nNKFu){;z8C z3&l}NB^=mG!p?v{e}N1o##pOa(Yr6O{|H?zG#+gW`9H4l*nXBSqQ)8f^r&0Tp>3Qt zMYIB3^M@&Xg2BzcLvCO`n>|J5&PiKhbfFYSnA}8Rhy`mNAP{=>oR)wA1`^HZtZ)q zpEoW|Z^;)SG<3;&Ja=laJoOgjFSFzj^pYE_w+%izS$EMtCU(tVCrHRpJzOsBL)kI7 z9yzy{boT?=CNX1&!-r8M?oT8Uap)H{iGr@#p!eh7lp75zqQ2-h(qC>*=^_;c(F;4J z5=1YAKyTBb1&vrL2qFWL(7grgR;$Q?hUlNK-}`5_PI}#0@loTa;YCl9q7L7 zMNBL(bLuMhtKGA%me#3@p_CU#4O)Wp39@g&|0EU$l%l13;nmcwn%W_)^rUl96_HD5 z;^`4w(%k6%lSBH|Tve_E^$6$bZwu*7D<@O5aG!+%cvqllp01o}J1FC@bvb8-KyX^! z*7eYy-OgPvVFEMHRSneOMk}+eAsC74)W6y$yhpm@aRZ{Z`nah9a(W*3zL}13#mq0< z<8*S1KGMfN5{<1XR_eQJas64MOXZgIAu@n?3RLm_o_%}m^#h}cZo#8?T)ODvFOW;v zL{C2Ncj)r`JxXHaE@Rxm=~AcvemyGZh+vW+2@1+Swhq|uo=D|Xf;3BpYgZ@&IE90p zb_+FzH?uHSJR1I63Gi%-wAEmpl0g5{p- z5p@=_03h3y#Lb3_*N9VX7WT@IgG%kKRxB1D%mK25b1;nG-*Z76L1Z(;aX;cTAK1OU zgba1H2JsKi*Hn6SD*wOOm7VhX)EPbhC$mpphdIzQleZfT_W7T}?)XG30;d}mIu^@( z{-@Fzaw#eR z3*|+J0H+y57b*waEpUU<4JCi%XG?y{BN4mgf(J|eltQCu5|B8{Sv%h0jyb2JftzS;ACx!bDV`igd?hgO zXTHROOyC5m6+Ztbbx_`K5eq=Sp%^1;6&&*1HAxGvKC~i>eVcuj7dV@858@$2pZy~M zD3RU({@2yve8X5>Lo!Fv33Lx_XQ`B(s?;fO(|Zmhe|fOYpwB1tekZfjJYRSG0qN+O z93BQdf+u#8H{eFuyMI^LL-`_V>_I;OFv-(JuQ{_=o#I4%HHY1QE9IMcuiU43D<3+^ z*=^8N7?D`<{9n=?(rLAxtH|9-%`s3FT1iX%rtrV}Oyfa)I#h?|rhp}wmxJxf2Dz)F zvj@3%xN*p96e6fT5<5;TZ=33}02)KNLT*O~&-CjnWy?O$A!uf6w1K=(ZtTVK%%Yt` zYzz=ZVQa)Hknt@XmWKh*l)UqKm={CYtb=L%-UV_yB65gZcxF0U9xKDehz@N9WLglgI_jsc(?Bh&P;AjC%;RCAwBaXk z&|I@6{8khvR`FSz{-CU<fpkqa0yjDGm)VYc^>Wwe}j{lzMp^ zXGZ0{yNmsRNCzoN0&Y#^S#YKgh6u(IoBJaUji2NhFk=y(P=f9GKuN=GV7Wy48-7@@ zj2?u;nGvpnl72i?fQ@ib#GDFc45ZUsK1*JooTlUU9xF&pGalS&3jqnpOlK`~xMd$w zO!q4ifPTWLGdn9kn`*t4MiwkeXTP{kw(FBYBzc3#WX1o3X(rSh7Fh-v9<<(O-wrBM z1CjJOnJgBIi;h4opy1z-7xD4>_%$Sb{cG7u!V~!q=|#{>pQCc|rB&!QUQUI1yktKd zkw)=!*t5&T_!`-!flL95_FKVcs;oP{J^oMX8^zzqtnE53F38=Qoy*m#3t3A;k2|{R zM8?3m+vH_?%H!|=YKP-g4YvF^wEx6?u6OJ%a*8ITi6(o$T~I4m-A0UCVGsvE8FNS7 zNjK-T5N%E*Xr4n4aeFI$R<*v5dA=F3FpMp(9aEJ^|6Yad`1XxErj1GSM)p9g3 z_`b=B81p`f(XF3gcz_#uKAq(Ib(CVU!Er$DzI`K>iqUN^X&ypG6IyD!EyP)Z-hHFXFrDlBlBJx|A zQ;er=2|>$y&Zw}p{0+IyHKtO?Za`^}849eQ`SiI_v8!J6DVg5#x3D9bK#djJe@!+f z#z=8gPwSF{d_}f|Cd(AVQi5;3{0Mi~u=imX_P+Qbc>{!EZ>~;j=YF)ueeuJU*j<7F zrZS7**7}S`%q9X4rphn^L?(**a_8?sO{E6{znaAUuo+$1wCU16%FSSkTE-!OGFJHD z3(^`PUJ1v(_n9|y$_}KrW9t2KU-lyqm)M&i|!${D@Iezr0NWce@T6--Kfa=_2Ea(82kzDWV(%YBd)x8B^l>zFmUIwlTM_b3r1GOq# z)F^ti9){{!fxKoOg{3<7_B7e#I#|0SzR@YJEQ<60p+)3$ecgFNX*f&!L5QkKrUr=bD32WqHj z=KtWP7dfm2nngGnQ}6^Y4^H0ikmuGfp7QID&_fW*wo16mfr^r*S}Vl`w*H4B&)0STaVrbw(SkztcTPRC#Zg70wPL6$X+rmTC$4Q#Y2|K!5X@e%X%tX>h`@d@^aufOxY+3?BD= zg}}Iv$x9zZ@{1Bmv}>-J%XFd3y)3&&2DPnNYk>qphFC&Y7m{BmiTpV*t-<0r^cp@J zgwr9}-59g}Lo*#Xoc&<_vZPhMB+efP90WC(F^TB$#8dwv5&=K&eS;@AR)AD)% zW|_G(n#bkx5U4V|O?)Yzz!5Sa$=R2X{R{S1K?);eMrNkICq1}q`TYmCc@+zDUe_~w z5cZDeLyU@k1r5fCxmt*=H#d943T|j)0H+1S;aEE>9EwkBlI}kt>J(ju#ZOB?zjF5$ zpXoohBPB=UkEW96%hGxPOh$9g_XfEe3KP

-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 pNR7#{Lml+0DC8gx`lGJc{8` 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�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 z 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