diff --git a/default.properties b/default.properties
new file mode 100644
index 0000000..dbf05f2
--- /dev/null
+++ b/default.properties
@@ -0,0 +1,11 @@
+# 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,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-5
diff --git a/res/anim/disappear.xml b/res/anim/disappear.xml
new file mode 100644
index 0000000..b1fd5e3
--- /dev/null
+++ b/res/anim/disappear.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/grow_from_bottom.xml b/res/anim/grow_from_bottom.xml
new file mode 100644
index 0000000..d2a371d
--- /dev/null
+++ b/res/anim/grow_from_bottom.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/grow_from_bottomleft_to_topright.xml b/res/anim/grow_from_bottomleft_to_topright.xml
new file mode 100644
index 0000000..a4bf4ea
--- /dev/null
+++ b/res/anim/grow_from_bottomleft_to_topright.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/grow_from_bottomright_to_topleft.xml b/res/anim/grow_from_bottomright_to_topleft.xml
new file mode 100644
index 0000000..1922b2b
--- /dev/null
+++ b/res/anim/grow_from_bottomright_to_topleft.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/grow_from_top.xml b/res/anim/grow_from_top.xml
new file mode 100644
index 0000000..ffd722c
--- /dev/null
+++ b/res/anim/grow_from_top.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/grow_from_topleft_to_bottomright.xml b/res/anim/grow_from_topleft_to_bottomright.xml
new file mode 100644
index 0000000..b67ebe5
--- /dev/null
+++ b/res/anim/grow_from_topleft_to_bottomright.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/grow_from_topright_to_bottomleft.xml b/res/anim/grow_from_topright_to_bottomleft.xml
new file mode 100644
index 0000000..fb19004
--- /dev/null
+++ b/res/anim/grow_from_topright_to_bottomleft.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/pump_bottom.xml b/res/anim/pump_bottom.xml
new file mode 100644
index 0000000..f681951
--- /dev/null
+++ b/res/anim/pump_bottom.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/pump_top.xml b/res/anim/pump_top.xml
new file mode 100644
index 0000000..65637b5
--- /dev/null
+++ b/res/anim/pump_top.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/rail.xml b/res/anim/rail.xml
new file mode 100644
index 0000000..2fdbe38
--- /dev/null
+++ b/res/anim/rail.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/res/anim/shrink_from_bottom.xml b/res/anim/shrink_from_bottom.xml
new file mode 100644
index 0000000..a98d592
--- /dev/null
+++ b/res/anim/shrink_from_bottom.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/shrink_from_bottomleft_to_topright.xml b/res/anim/shrink_from_bottomleft_to_topright.xml
new file mode 100644
index 0000000..ebde343
--- /dev/null
+++ b/res/anim/shrink_from_bottomleft_to_topright.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/shrink_from_bottomright_to_topleft.xml b/res/anim/shrink_from_bottomright_to_topleft.xml
new file mode 100644
index 0000000..d4ed513
--- /dev/null
+++ b/res/anim/shrink_from_bottomright_to_topleft.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/shrink_from_top.xml b/res/anim/shrink_from_top.xml
new file mode 100644
index 0000000..89cd8f4
--- /dev/null
+++ b/res/anim/shrink_from_top.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/anim/shrink_from_topleft_to_bottomright.xml b/res/anim/shrink_from_topleft_to_bottomright.xml
new file mode 100644
index 0000000..a39681a
--- /dev/null
+++ b/res/anim/shrink_from_topleft_to_bottomright.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/anim/shrink_from_topright_to_bottomleft.xml b/res/anim/shrink_from_topright_to_bottomleft.xml
new file mode 100644
index 0000000..d4064fc
--- /dev/null
+++ b/res/anim/shrink_from_topright_to_bottomleft.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/res/drawable-hdpi/addcontact.png b/res/drawable-hdpi/addcontact.png
new file mode 100644
index 0000000..420f362
Binary files /dev/null and b/res/drawable-hdpi/addcontact.png differ
diff --git a/res/drawable-hdpi/arrowdown.png b/res/drawable-hdpi/arrowdown.png
new file mode 100644
index 0000000..e3f445c
Binary files /dev/null and b/res/drawable-hdpi/arrowdown.png differ
diff --git a/res/drawable-hdpi/arrowleft.png b/res/drawable-hdpi/arrowleft.png
new file mode 100644
index 0000000..f5725f6
Binary files /dev/null and b/res/drawable-hdpi/arrowleft.png differ
diff --git a/res/drawable-hdpi/arrowright.png b/res/drawable-hdpi/arrowright.png
new file mode 100644
index 0000000..a960c09
Binary files /dev/null and b/res/drawable-hdpi/arrowright.png differ
diff --git a/res/drawable-hdpi/arrowup.png b/res/drawable-hdpi/arrowup.png
new file mode 100644
index 0000000..987c54a
Binary files /dev/null and b/res/drawable-hdpi/arrowup.png differ
diff --git a/res/drawable-hdpi/btn_strip_trans_left_pressed.9.png b/res/drawable-hdpi/btn_strip_trans_left_pressed.9.png
new file mode 100644
index 0000000..ceddd76
Binary files /dev/null and b/res/drawable-hdpi/btn_strip_trans_left_pressed.9.png differ
diff --git a/res/drawable-hdpi/btn_strip_trans_left_selected.9.png b/res/drawable-hdpi/btn_strip_trans_left_selected.9.png
new file mode 100644
index 0000000..bc40887
Binary files /dev/null and b/res/drawable-hdpi/btn_strip_trans_left_selected.9.png differ
diff --git a/res/drawable-hdpi/btn_strip_trans_middle_normal.9.png b/res/drawable-hdpi/btn_strip_trans_middle_normal.9.png
new file mode 100644
index 0000000..77ee4be
Binary files /dev/null and b/res/drawable-hdpi/btn_strip_trans_middle_normal.9.png differ
diff --git a/res/drawable-hdpi/btn_strip_trans_middle_pressed.9.png b/res/drawable-hdpi/btn_strip_trans_middle_pressed.9.png
new file mode 100644
index 0000000..3cc35e7
Binary files /dev/null and b/res/drawable-hdpi/btn_strip_trans_middle_pressed.9.png differ
diff --git a/res/drawable-hdpi/btn_strip_trans_middle_selected.9.png b/res/drawable-hdpi/btn_strip_trans_middle_selected.9.png
new file mode 100644
index 0000000..736e9b2
Binary files /dev/null and b/res/drawable-hdpi/btn_strip_trans_middle_selected.9.png differ
diff --git a/res/drawable-hdpi/calllog.png b/res/drawable-hdpi/calllog.png
new file mode 100644
index 0000000..3825354
Binary files /dev/null and b/res/drawable-hdpi/calllog.png differ
diff --git a/res/drawable-hdpi/calllog1.png b/res/drawable-hdpi/calllog1.png
new file mode 100644
index 0000000..f52b6c8
Binary files /dev/null and b/res/drawable-hdpi/calllog1.png differ
diff --git a/res/drawable-hdpi/delete.png b/res/drawable-hdpi/delete.png
new file mode 100644
index 0000000..2c9c0c7
Binary files /dev/null and b/res/drawable-hdpi/delete.png differ
diff --git a/res/drawable-hdpi/ic_accept.png b/res/drawable-hdpi/ic_accept.png
new file mode 100644
index 0000000..9a49010
Binary files /dev/null and b/res/drawable-hdpi/ic_accept.png differ
diff --git a/res/drawable-hdpi/ic_add.png b/res/drawable-hdpi/ic_add.png
new file mode 100644
index 0000000..6c2732a
Binary files /dev/null and b/res/drawable-hdpi/ic_add.png differ
diff --git a/res/drawable-hdpi/ic_contact_list_picture.png b/res/drawable-hdpi/ic_contact_list_picture.png
new file mode 100644
index 0000000..b96fbf4
Binary files /dev/null and b/res/drawable-hdpi/ic_contact_list_picture.png differ
diff --git a/res/drawable-hdpi/ic_list_more.png b/res/drawable-hdpi/ic_list_more.png
new file mode 100644
index 0000000..36dacde
Binary files /dev/null and b/res/drawable-hdpi/ic_list_more.png differ
diff --git a/res/drawable-hdpi/ic_list_more_selected.png b/res/drawable-hdpi/ic_list_more_selected.png
new file mode 100644
index 0000000..2395823
Binary files /dev/null and b/res/drawable-hdpi/ic_list_more_selected.png differ
diff --git a/res/drawable-hdpi/ic_up.png b/res/drawable-hdpi/ic_up.png
new file mode 100644
index 0000000..3515ded
Binary files /dev/null and b/res/drawable-hdpi/ic_up.png differ
diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-hdpi/icon.png differ
diff --git a/res/drawable-hdpi/incoming.png b/res/drawable-hdpi/incoming.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-hdpi/incoming.png differ
diff --git a/res/drawable-hdpi/miss.png b/res/drawable-hdpi/miss.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-hdpi/miss.png differ
diff --git a/res/drawable-hdpi/outgoing.png b/res/drawable-hdpi/outgoing.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-hdpi/outgoing.png differ
diff --git a/res/drawable-hdpi/phonecall1.png b/res/drawable-hdpi/phonecall1.png
new file mode 100644
index 0000000..886241f
Binary files /dev/null and b/res/drawable-hdpi/phonecall1.png differ
diff --git a/res/drawable-hdpi/photoframe.png b/res/drawable-hdpi/photoframe.png
new file mode 100644
index 0000000..2545086
Binary files /dev/null and b/res/drawable-hdpi/photoframe.png differ
diff --git a/res/drawable-hdpi/photoframe2.png b/res/drawable-hdpi/photoframe2.png
new file mode 100644
index 0000000..6d5e82b
Binary files /dev/null and b/res/drawable-hdpi/photoframe2.png differ
diff --git a/res/drawable-hdpi/photoframe3.png b/res/drawable-hdpi/photoframe3.png
new file mode 100644
index 0000000..3a730a3
Binary files /dev/null and b/res/drawable-hdpi/photoframe3.png differ
diff --git a/res/drawable-hdpi/photoframe4.png b/res/drawable-hdpi/photoframe4.png
new file mode 100644
index 0000000..05958e8
Binary files /dev/null and b/res/drawable-hdpi/photoframe4.png differ
diff --git a/res/drawable-hdpi/quickaction_arrow_down.png b/res/drawable-hdpi/quickaction_arrow_down.png
new file mode 100644
index 0000000..718db62
Binary files /dev/null and b/res/drawable-hdpi/quickaction_arrow_down.png differ
diff --git a/res/drawable-hdpi/quickaction_arrow_up.png b/res/drawable-hdpi/quickaction_arrow_up.png
new file mode 100644
index 0000000..f876f40
Binary files /dev/null and b/res/drawable-hdpi/quickaction_arrow_up.png differ
diff --git a/res/drawable-hdpi/quickaction_background.png b/res/drawable-hdpi/quickaction_background.png
new file mode 100644
index 0000000..8d2b8fc
Binary files /dev/null and b/res/drawable-hdpi/quickaction_background.png differ
diff --git a/res/drawable-hdpi/quickaction_bottom_frame.9.png b/res/drawable-hdpi/quickaction_bottom_frame.9.png
new file mode 100644
index 0000000..50749da
Binary files /dev/null and b/res/drawable-hdpi/quickaction_bottom_frame.9.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_btn_normal.9.png b/res/drawable-hdpi/quickaction_slider_btn_normal.9.png
new file mode 100644
index 0000000..a5143bc
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_btn_normal.9.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_btn_on.9.png b/res/drawable-hdpi/quickaction_slider_btn_on.9.png
new file mode 100644
index 0000000..c0165a6
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_btn_on.9.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_btn_pressed.9.png b/res/drawable-hdpi/quickaction_slider_btn_pressed.9.png
new file mode 100644
index 0000000..5f8bfe6
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_btn_pressed.9.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_btn_selected.9.png b/res/drawable-hdpi/quickaction_slider_btn_selected.9.png
new file mode 100644
index 0000000..8955f7e
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_btn_selected.9.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_grip_left.png b/res/drawable-hdpi/quickaction_slider_grip_left.png
new file mode 100644
index 0000000..75e61e1
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_grip_left.png differ
diff --git a/res/drawable-hdpi/quickaction_slider_grip_right.png b/res/drawable-hdpi/quickaction_slider_grip_right.png
new file mode 100644
index 0000000..68440cb
Binary files /dev/null and b/res/drawable-hdpi/quickaction_slider_grip_right.png differ
diff --git a/res/drawable-hdpi/quickaction_top_frame.9.png b/res/drawable-hdpi/quickaction_top_frame.9.png
new file mode 100644
index 0000000..8b6543e
Binary files /dev/null and b/res/drawable-hdpi/quickaction_top_frame.9.png differ
diff --git a/res/drawable-hdpi/sms1.png b/res/drawable-hdpi/sms1.png
new file mode 100644
index 0000000..5a3d9de
Binary files /dev/null and b/res/drawable-hdpi/sms1.png differ
diff --git a/res/drawable-hdpi/textfield_default.9.png b/res/drawable-hdpi/textfield_default.9.png
new file mode 100644
index 0000000..4c20179
Binary files /dev/null and b/res/drawable-hdpi/textfield_default.9.png differ
diff --git a/res/drawable-hdpi/viewcontact2.png b/res/drawable-hdpi/viewcontact2.png
new file mode 100644
index 0000000..1e48ebd
Binary files /dev/null and b/res/drawable-hdpi/viewcontact2.png differ
diff --git a/res/drawable-ldpi/addcontact.png b/res/drawable-ldpi/addcontact.png
new file mode 100644
index 0000000..0184801
Binary files /dev/null and b/res/drawable-ldpi/addcontact.png differ
diff --git a/res/drawable-ldpi/arrowdown.png b/res/drawable-ldpi/arrowdown.png
new file mode 100644
index 0000000..a64df1a
Binary files /dev/null and b/res/drawable-ldpi/arrowdown.png differ
diff --git a/res/drawable-ldpi/arrowleft.png b/res/drawable-ldpi/arrowleft.png
new file mode 100644
index 0000000..5b57406
Binary files /dev/null and b/res/drawable-ldpi/arrowleft.png differ
diff --git a/res/drawable-ldpi/arrowright.png b/res/drawable-ldpi/arrowright.png
new file mode 100644
index 0000000..c036b75
Binary files /dev/null and b/res/drawable-ldpi/arrowright.png differ
diff --git a/res/drawable-ldpi/arrowup.png b/res/drawable-ldpi/arrowup.png
new file mode 100644
index 0000000..d646a16
Binary files /dev/null and b/res/drawable-ldpi/arrowup.png differ
diff --git a/res/drawable-ldpi/delete.png b/res/drawable-ldpi/delete.png
new file mode 100644
index 0000000..e06ec1a
Binary files /dev/null and b/res/drawable-ldpi/delete.png differ
diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/res/drawable-ldpi/icon.png differ
diff --git a/res/drawable-ldpi/incoming.png b/res/drawable-ldpi/incoming.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-ldpi/incoming.png differ
diff --git a/res/drawable-ldpi/miss.png b/res/drawable-ldpi/miss.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-ldpi/miss.png differ
diff --git a/res/drawable-ldpi/outgoing.png b/res/drawable-ldpi/outgoing.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-ldpi/outgoing.png differ
diff --git a/res/drawable-ldpi/phonecall1.png b/res/drawable-ldpi/phonecall1.png
new file mode 100644
index 0000000..77ba9bd
Binary files /dev/null and b/res/drawable-ldpi/phonecall1.png differ
diff --git a/res/drawable-ldpi/sms1.png b/res/drawable-ldpi/sms1.png
new file mode 100644
index 0000000..b858da5
Binary files /dev/null and b/res/drawable-ldpi/sms1.png differ
diff --git a/res/drawable-ldpi/viewcontact2.png b/res/drawable-ldpi/viewcontact2.png
new file mode 100644
index 0000000..2dc7079
Binary files /dev/null and b/res/drawable-ldpi/viewcontact2.png differ
diff --git a/res/drawable-mdpi/addcontact.png b/res/drawable-mdpi/addcontact.png
new file mode 100644
index 0000000..38c4432
Binary files /dev/null and b/res/drawable-mdpi/addcontact.png differ
diff --git a/res/drawable-mdpi/arrowdown.png b/res/drawable-mdpi/arrowdown.png
new file mode 100644
index 0000000..88476f0
Binary files /dev/null and b/res/drawable-mdpi/arrowdown.png differ
diff --git a/res/drawable-mdpi/arrowleft.png b/res/drawable-mdpi/arrowleft.png
new file mode 100644
index 0000000..f7357ca
Binary files /dev/null and b/res/drawable-mdpi/arrowleft.png differ
diff --git a/res/drawable-mdpi/arrowright.png b/res/drawable-mdpi/arrowright.png
new file mode 100644
index 0000000..6f1c7fd
Binary files /dev/null and b/res/drawable-mdpi/arrowright.png differ
diff --git a/res/drawable-mdpi/arrowup.png b/res/drawable-mdpi/arrowup.png
new file mode 100644
index 0000000..2ca5228
Binary files /dev/null and b/res/drawable-mdpi/arrowup.png differ
diff --git a/res/drawable-mdpi/delete.png b/res/drawable-mdpi/delete.png
new file mode 100644
index 0000000..ef2dbdb
Binary files /dev/null and b/res/drawable-mdpi/delete.png differ
diff --git a/res/drawable-mdpi/ic_accept.png b/res/drawable-mdpi/ic_accept.png
new file mode 100644
index 0000000..205572d
Binary files /dev/null and b/res/drawable-mdpi/ic_accept.png differ
diff --git a/res/drawable-mdpi/ic_add.png b/res/drawable-mdpi/ic_add.png
new file mode 100644
index 0000000..1f974bf
Binary files /dev/null and b/res/drawable-mdpi/ic_add.png differ
diff --git a/res/drawable-mdpi/ic_contact_list_picture.png b/res/drawable-mdpi/ic_contact_list_picture.png
new file mode 100644
index 0000000..f8aa4ba
Binary files /dev/null and b/res/drawable-mdpi/ic_contact_list_picture.png differ
diff --git a/res/drawable-mdpi/ic_list_more.png b/res/drawable-mdpi/ic_list_more.png
new file mode 100644
index 0000000..789183c
Binary files /dev/null and b/res/drawable-mdpi/ic_list_more.png differ
diff --git a/res/drawable-mdpi/ic_list_more_selected.png b/res/drawable-mdpi/ic_list_more_selected.png
new file mode 100644
index 0000000..9416da3
Binary files /dev/null and b/res/drawable-mdpi/ic_list_more_selected.png differ
diff --git a/res/drawable-mdpi/ic_up.png b/res/drawable-mdpi/ic_up.png
new file mode 100644
index 0000000..483f6d1
Binary files /dev/null and b/res/drawable-mdpi/ic_up.png differ
diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..35ca9c6
Binary files /dev/null and b/res/drawable-mdpi/icon.png differ
diff --git a/res/drawable-mdpi/incoming.png b/res/drawable-mdpi/incoming.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-mdpi/incoming.png differ
diff --git a/res/drawable-mdpi/miss.png b/res/drawable-mdpi/miss.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-mdpi/miss.png differ
diff --git a/res/drawable-mdpi/outgoing.png b/res/drawable-mdpi/outgoing.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-mdpi/outgoing.png differ
diff --git a/res/drawable-mdpi/phonecall1.png b/res/drawable-mdpi/phonecall1.png
new file mode 100644
index 0000000..ee07e06
Binary files /dev/null and b/res/drawable-mdpi/phonecall1.png differ
diff --git a/res/drawable-mdpi/photoframe.png b/res/drawable-mdpi/photoframe.png
new file mode 100644
index 0000000..26ac608
Binary files /dev/null and b/res/drawable-mdpi/photoframe.png differ
diff --git a/res/drawable-mdpi/quickaction_arrow_down.png b/res/drawable-mdpi/quickaction_arrow_down.png
new file mode 100644
index 0000000..6e8ee25
Binary files /dev/null and b/res/drawable-mdpi/quickaction_arrow_down.png differ
diff --git a/res/drawable-mdpi/quickaction_arrow_up.png b/res/drawable-mdpi/quickaction_arrow_up.png
new file mode 100644
index 0000000..b907d5b
Binary files /dev/null and b/res/drawable-mdpi/quickaction_arrow_up.png differ
diff --git a/res/drawable-mdpi/quickaction_bottom_frame.9.png b/res/drawable-mdpi/quickaction_bottom_frame.9.png
new file mode 100644
index 0000000..aa129b4
Binary files /dev/null and b/res/drawable-mdpi/quickaction_bottom_frame.9.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_background.png b/res/drawable-mdpi/quickaction_slider_background.png
new file mode 100644
index 0000000..f11d9c9
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_background.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_btn_normal.9.png b/res/drawable-mdpi/quickaction_slider_btn_normal.9.png
new file mode 100644
index 0000000..e7bb48d
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_btn_normal.9.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_btn_on.9.png b/res/drawable-mdpi/quickaction_slider_btn_on.9.png
new file mode 100644
index 0000000..655e6fd
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_btn_on.9.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_btn_pressed.9.png b/res/drawable-mdpi/quickaction_slider_btn_pressed.9.png
new file mode 100644
index 0000000..a4bc468
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_btn_pressed.9.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_btn_selected.9.png b/res/drawable-mdpi/quickaction_slider_btn_selected.9.png
new file mode 100644
index 0000000..474d095
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_btn_selected.9.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_grip_left.png b/res/drawable-mdpi/quickaction_slider_grip_left.png
new file mode 100644
index 0000000..aab811b
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_grip_left.png differ
diff --git a/res/drawable-mdpi/quickaction_slider_grip_right.png b/res/drawable-mdpi/quickaction_slider_grip_right.png
new file mode 100644
index 0000000..b44f1e2
Binary files /dev/null and b/res/drawable-mdpi/quickaction_slider_grip_right.png differ
diff --git a/res/drawable-mdpi/quickaction_top_frame.9.png b/res/drawable-mdpi/quickaction_top_frame.9.png
new file mode 100644
index 0000000..6420712
Binary files /dev/null and b/res/drawable-mdpi/quickaction_top_frame.9.png differ
diff --git a/res/drawable-mdpi/sms1.png b/res/drawable-mdpi/sms1.png
new file mode 100644
index 0000000..2e317ae
Binary files /dev/null and b/res/drawable-mdpi/sms1.png differ
diff --git a/res/drawable-mdpi/textfield_default.9.png b/res/drawable-mdpi/textfield_default.9.png
new file mode 100644
index 0000000..cc78e6c
Binary files /dev/null and b/res/drawable-mdpi/textfield_default.9.png differ
diff --git a/res/drawable-mdpi/viewcontact2.png b/res/drawable-mdpi/viewcontact2.png
new file mode 100644
index 0000000..2f2dbba
Binary files /dev/null and b/res/drawable-mdpi/viewcontact2.png differ
diff --git a/res/drawable/arrow_down.png b/res/drawable/arrow_down.png
new file mode 100644
index 0000000..05e6a59
Binary files /dev/null and b/res/drawable/arrow_down.png differ
diff --git a/res/drawable/arrow_up.png b/res/drawable/arrow_up.png
new file mode 100644
index 0000000..4412938
Binary files /dev/null and b/res/drawable/arrow_up.png differ
diff --git a/res/drawable/btn_strip_trans_middle.xml b/res/drawable/btn_strip_trans_middle.xml
new file mode 100644
index 0000000..b0b715a
--- /dev/null
+++ b/res/drawable/btn_strip_trans_middle.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/drawable/expandable_list_group_indicator_arrow.xml b/res/drawable/expandable_list_group_indicator_arrow.xml
new file mode 100644
index 0000000..958ffc6
--- /dev/null
+++ b/res/drawable/expandable_list_group_indicator_arrow.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/res/drawable/list_button.xml b/res/drawable/list_button.xml
new file mode 100644
index 0000000..f1f6e75
--- /dev/null
+++ b/res/drawable/list_button.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/res/drawable/popup.9.png b/res/drawable/popup.9.png
new file mode 100644
index 0000000..3342272
Binary files /dev/null and b/res/drawable/popup.9.png differ
diff --git a/res/drawable/quickaction_slider_btn.xml b/res/drawable/quickaction_slider_btn.xml
new file mode 100644
index 0000000..f1ab167
--- /dev/null
+++ b/res/drawable/quickaction_slider_btn.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/action_item.xml b/res/layout/action_item.xml
new file mode 100644
index 0000000..c0c5438
--- /dev/null
+++ b/res/layout/action_item.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/calllog_filter_dialog.xml b/res/layout/calllog_filter_dialog.xml
new file mode 100644
index 0000000..edc4316
--- /dev/null
+++ b/res/layout/calllog_filter_dialog.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/calllog_filter_name_list_dialog.xml b/res/layout/calllog_filter_name_list_dialog.xml
new file mode 100644
index 0000000..b9e41df
--- /dev/null
+++ b/res/layout/calllog_filter_name_list_dialog.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/calllog_filter_number_list_dialog.xml b/res/layout/calllog_filter_number_list_dialog.xml
new file mode 100644
index 0000000..d14cd67
--- /dev/null
+++ b/res/layout/calllog_filter_number_list_dialog.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/expandable_three_lines_icon_text_child_view.xml b/res/layout/expandable_three_lines_icon_text_child_view.xml
new file mode 100644
index 0000000..526c1fd
--- /dev/null
+++ b/res/layout/expandable_three_lines_icon_text_child_view.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/expandable_three_lines_icon_text_group_view.xml b/res/layout/expandable_three_lines_icon_text_group_view.xml
new file mode 100644
index 0000000..45b353b
--- /dev/null
+++ b/res/layout/expandable_three_lines_icon_text_group_view.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..6785f18
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/main_choice_dialog.xml b/res/layout/main_choice_dialog.xml
new file mode 100644
index 0000000..58d49e8
--- /dev/null
+++ b/res/layout/main_choice_dialog.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/res/layout/main_empty.xml b/res/layout/main_empty.xml
new file mode 100644
index 0000000..5aee4d9
--- /dev/null
+++ b/res/layout/main_empty.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/res/layout/popup.xml b/res/layout/popup.xml
new file mode 100644
index 0000000..a4af4e6
--- /dev/null
+++ b/res/layout/popup.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/quickaction.xml b/res/layout/quickaction.xml
new file mode 100644
index 0000000..1782a66
--- /dev/null
+++ b/res/layout/quickaction.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/single_choice_for_sorting.xml b/res/layout/single_choice_for_sorting.xml
new file mode 100644
index 0000000..b0d0c0c
--- /dev/null
+++ b/res/layout/single_choice_for_sorting.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/res/layout/three_lines_icon_text_view.xml b/res/layout/three_lines_icon_text_view.xml
new file mode 100644
index 0000000..b6dca8a
--- /dev/null
+++ b/res/layout/three_lines_icon_text_view.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..653888e
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,40 @@
+
+
+ #7f00
+ #770000ff
+ #7700ff00
+ #77ffff00
+
+ #77ff5555
+ #77ff2323
+ #77ffe1e1
+
+ #ff000000
+ #e0000000
+ #00000000
+
+ #f00
+ #0000ff
+ #f0f0
+ #ffffff00
+ #ffffffff
+ #ff000000
+ #ff888888
+ #88888888
+
+ #77ffe1e1
+
+ #ff355689
+ #ffffffff
+ #ff000000
+ #ff355689
+ #ff7081a3
+ #ffffffff
+ #ffd5ddeb
+ #ffe3e8f1
+ #40ffffff
+
+ #ff999999
+
+ #ff202020
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100644
index 0000000..4a7a743
--- /dev/null
+++ b/res/values/dimens.xml
@@ -0,0 +1,42 @@
+
+
+
+
+ 30dip
+ 37dip
+ 20dip
+
+ 76dip
+
+
+ 40dip
+ 25dip
+
+ 50dip
+ 56dip
+
+
+ 4dip
+ 11dip
+ 4dip
+ 4dip
+ 8dip
+ 5dip
+ 14dip
+ 5dip
+ 5dip
+ 56dip
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..08eb966
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+ Hello World, Main!
+ Advanced Phone Log
+ Not Available
+
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..1146bc2
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/roman10reborn/apl/data2/AdvancedPhoneLogRecord.java b/src/roman10reborn/apl/data2/AdvancedPhoneLogRecord.java
new file mode 100644
index 0000000..bbb7b3f
--- /dev/null
+++ b/src/roman10reborn/apl/data2/AdvancedPhoneLogRecord.java
@@ -0,0 +1,28 @@
+package roman10reborn.apl.data2;
+
+import java.util.Date;
+
+public class AdvancedPhoneLogRecord {
+ public int aplr_dataId;
+ public String aplr_number;
+ public String aplr_name;
+ public Date aplr_time;
+ public int aplr_type;
+ public int aplr_duration;
+ public int aplr_id; //the id in the database
+
+ public AdvancedPhoneLogRecord(String _number, String _name, Date _time, int _type,
+ int _duration, int _id, int _dataId) {
+ aplr_number = _number;
+ aplr_name = _name;
+ aplr_time = _time;
+ aplr_type = _type;
+ aplr_duration = _duration;
+ aplr_id = _id;
+ aplr_dataId = _dataId;
+ }
+
+ public boolean isSameContact(AdvancedPhoneLogRecord _a) {
+ return (this.aplr_number.compareTo(_a.aplr_number)==0);
+ }
+}
diff --git a/src/roman10reborn/apl/data2/BooleanArrayList.java b/src/roman10reborn/apl/data2/BooleanArrayList.java
new file mode 100644
index 0000000..777bebf
--- /dev/null
+++ b/src/roman10reborn/apl/data2/BooleanArrayList.java
@@ -0,0 +1,295 @@
+package roman10reborn.apl.data2;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.io.IOException;
+
+/**
+ * ArrayList of boolean primitives.
+ */
+public class BooleanArrayList implements Serializable {
+
+ private boolean[] array;
+ private int size;
+
+ public static int initialCapacity = 10;
+
+ /**
+ * Constructs an empty list with an initial capacity.
+ */
+ public BooleanArrayList() {
+ this(initialCapacity);
+ }
+
+ /**
+ * Constructs an empty list with the specified initial capacity.
+ */
+ public BooleanArrayList(int initialCapacity) {
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException("Capacity can't be negative: " + initialCapacity);
+ }
+ array = new boolean[initialCapacity];
+ size = 0;
+ }
+
+ /**
+ * Constructs a list containing the elements of the specified array.
+ * The list instance has an initial capacity of 110% the size of the specified array.
+ */
+ public BooleanArrayList(boolean[] data) {
+ array = new boolean[(int) (data.length * 1.1) + 1];
+ size = data.length;
+ System.arraycopy(data, 0, array, 0, size);
+ }
+
+ // ---------------------------------------------------------------- conversion
+
+ /**
+ * Returns an array containing all of the elements in this list in the correct order.
+ */
+ public boolean[] toArray() {
+ boolean[] result = new boolean[size];
+ System.arraycopy(array, 0, result, 0, size);
+ return result;
+ }
+
+ // ---------------------------------------------------------------- methods
+
+ /**
+ * Returns the element at the specified position in this list.
+ */
+ public boolean get(int index) {
+ checkRange(index);
+ return array[index];
+ }
+
+ /**
+ * Returns the number of elements in this list.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Removes the element at the specified position in this list.
+ * Shifts any subsequent elements to the left (subtracts
+ * one from their indices).
+ *
+ * @param index the index of the element to remove
+ * @return the value of the element that was removed
+ * @throws UnsupportedOperationException when this operation is not
+ * supported
+ * @throws IndexOutOfBoundsException if the specified index is out of range
+ */
+ public boolean remove(int index) {
+ checkRange(index);
+ boolean oldval = array[index];
+ int numtomove = size - index - 1;
+ if (numtomove > 0) {
+ System.arraycopy(array, index + 1, array, index, numtomove);
+ }
+ size--;
+ return oldval;
+ }
+ /**
+ * Removes from this list all of the elements whose index is between fromIndex,
+ * inclusive and toIndex, exclusive. Shifts any succeeding elements to the left (reduces their index).
+ */
+ public void removeRange(int fromIndex, int toIndex) {
+ checkRange(fromIndex);
+ checkRange(toIndex);
+ if (fromIndex >= toIndex) {
+ return;
+ }
+ int numtomove = size - toIndex;
+ if (numtomove > 0) {
+ System.arraycopy(array, toIndex, array, fromIndex, numtomove);
+ }
+ size -= (toIndex - fromIndex);
+ }
+
+ /**
+ * Replaces the element at the specified position in this list with the specified element.
+ *
+ * @param index the index of the element to change
+ * @param element the value to be stored at the specified position
+ * @return the value previously stored at the specified position
+ */
+ public boolean set(int index, boolean element) {
+ checkRange(index);
+ boolean oldval = array[index];
+ array[index] = element;
+ return oldval;
+ }
+
+ /**
+ * Appends the specified element to the end of this list.
+ */
+ public void add(boolean element) {
+ ensureCapacity(size + 1);
+ array[size++] = element;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in this list.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ * @param index the index at which to insert the element
+ * @param element the value to insert
+ */
+ public void add(int index, boolean element) {
+ checkRangeIncludingEndpoint(index);
+ ensureCapacity(size + 1);
+ int numtomove = size - index;
+ System.arraycopy(array, index, array, index + 1, numtomove);
+ array[index] = element;
+ size++;
+ }
+
+ /**
+ * Appends all of the elements in the specified array to the end of this list.
+ */
+ public void addAll(boolean[] data) {
+ int dataLen = data.length;
+ if (dataLen == 0) {
+ return;
+ }
+ int newcap = size + (int) (dataLen * 1.1) + 1;
+ ensureCapacity(newcap);
+ System.arraycopy(data, 0, array, size, dataLen);
+ size += dataLen;
+ }
+
+ /**
+ * Appends all of the elements in the specified array at the specified position in this list.
+ */
+ public void addAll(int index, boolean[] data) {
+ int dataLen = data.length;
+ if (dataLen == 0) {
+ return;
+ }
+ int newcap = size + (int) (dataLen * 1.1) + 1;
+ ensureCapacity(newcap);
+ System.arraycopy(array, index, array, index + dataLen, size - index);
+ System.arraycopy(data, 0, array, index, dataLen);
+ size += dataLen;
+ }
+
+ /**
+ * Removes all of the elements from this list.
+ * The list will be empty after this call returns.
+ */
+ public void clear() {
+ size = 0;
+ }
+
+ // ---------------------------------------------------------------- search
+
+ /**
+ * Returns true if this list contains the specified element.
+ */
+ public boolean contains(boolean data) {
+ for (int i = 0; i < size; i++) {
+ if (array[i] == data) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Searches for the first occurence of the given argument.
+ */
+ public int indexOf(boolean data) {
+ for (int i = 0; i < size; i++) {
+ if (array[i] == data) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index of the last occurrence of the specified object in this list.
+ */
+ public int lastIndexOf(boolean data) {
+ for (int i = size - 1; i >= 0; i--) {
+ if (array[i] == data) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Tests if this list has no elements.
+ */
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+
+
+ // ---------------------------------------------------------------- capacity
+
+ /**
+ * Increases the capacity of this ArrayList instance, if necessary,
+ * to ensure that it can hold at least the number of elements specified by
+ * the minimum capacity argument.
+ */
+ public void ensureCapacity(int mincap) {
+ if (mincap > array.length) {
+ int newcap = ((array.length * 3) >> 1) + 1;
+ boolean[] olddata = array;
+ array = new boolean[newcap < mincap ? mincap : newcap];
+ System.arraycopy(olddata, 0, array, 0, size);
+ }
+ }
+
+ /**
+ * Trims the capacity of this instance to be the list's current size.
+ * An application can use this operation to minimize the storage of some instance.
+ */
+ public void trimToSize() {
+ if (size < array.length) {
+ boolean[] olddata = array;
+ array = new boolean[size];
+ System.arraycopy(olddata, 0, array, 0, size);
+ }
+ }
+
+ // ---------------------------------------------------------------- serializable
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeInt(array.length);
+ for (int i = 0; i < size; i++) {
+ out.writeBoolean(array[i]);
+ }
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ array = new boolean[in.readInt()];
+ for (int i = 0; i < size; i++) {
+ array[i] = in.readBoolean();
+ }
+ }
+
+ // ---------------------------------------------------------------- privates
+
+ private void checkRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException("Index should be at least 0 and less than " + size + ", found " + index);
+ }
+ }
+
+ private void checkRangeIncludingEndpoint(int index) {
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException("Index should be at least 0 and at most " + size + ", found " + index);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/roman10reborn/apl/main/ContactAccessor.java b/src/roman10reborn/apl/main/ContactAccessor.java
new file mode 100644
index 0000000..1dab088
--- /dev/null
+++ b/src/roman10reborn/apl/main/ContactAccessor.java
@@ -0,0 +1,35 @@
+package roman10reborn.apl.main;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import roman10reborn.apl.main.ContactAccessorOldApi;
+import roman10reborn.apl.main.ContactAccessorNewApi;
+
+public abstract class ContactAccessor {
+ private static ContactAccessor sInstance;
+ public static ContactAccessor getInstance() {
+ if (sInstance == null) {
+ String className;
+ int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
+ if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
+ className = "ContactAccessorOldApi";
+ } else {
+ className = "ContactAccessorNewApi";
+ }
+ try {
+ Class extends ContactAccessor> clazz =
+ Class.forName("roman10reborn.apl.main." + className).asSubclass(ContactAccessor.class);
+// Class.forName(ContactAccessor.class.getPackage() + "." + className)
+// .asSubclass(ContactAccessor.class);
+ sInstance = clazz.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return sInstance;
+ }
+ public abstract Intent getAddToContactIntent(String number);
+ public abstract Intent getViewContactIntent();
+ public abstract void viewContact(Context mContext, String _number);
+}
diff --git a/src/roman10reborn/apl/main/ContactAccessorNewApi.java b/src/roman10reborn/apl/main/ContactAccessorNewApi.java
new file mode 100644
index 0000000..aefa01e
--- /dev/null
+++ b/src/roman10reborn/apl/main/ContactAccessorNewApi.java
@@ -0,0 +1,57 @@
+package roman10reborn.apl.main;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.Intents.Insert;
+
+public class ContactAccessorNewApi extends ContactAccessor{
+ @Override
+ public Intent getAddToContactIntent(String number) {
+ Intent l_intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ l_intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+ l_intent.putExtra(Insert.PHONE, number);
+ return l_intent;
+ }
+
+ @Override
+ public Intent getViewContactIntent() {
+ return null;
+ }
+
+ public void viewContact(Context mContext, String _number) {
+ final String[] PHONES_PROJECTION = new String[] {
+ PhoneLookup._ID,
+ PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.TYPE,
+ PhoneLookup.LABEL,
+ PhoneLookup.NUMBER,
+ };
+ final int COLUMN_INDEX_ID = 0;
+ Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(_number));
+ Cursor l_phoneCursor = mContext.getContentResolver().query(phoneUri, PHONES_PROJECTION, null, null, null);
+ Uri l_personUri = null;
+ try {
+ if (l_phoneCursor != null && l_phoneCursor.moveToFirst()) {
+ long personId = l_phoneCursor.getLong(COLUMN_INDEX_ID);
+ l_personUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, personId);
+ } else {
+
+ }
+ } finally {
+ if (l_phoneCursor != null) l_phoneCursor.close();
+ }
+ if (l_personUri!=null) {
+ Intent l_intent = new Intent(Intent.ACTION_VIEW, l_personUri);
+ l_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(l_intent);
+ }
+ }
+
+
+
+}
diff --git a/src/roman10reborn/apl/main/ContactAccessorOldApi.java b/src/roman10reborn/apl/main/ContactAccessorOldApi.java
new file mode 100644
index 0000000..e86a41a
--- /dev/null
+++ b/src/roman10reborn/apl/main/ContactAccessorOldApi.java
@@ -0,0 +1,21 @@
+package roman10reborn.apl.main;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class ContactAccessorOldApi extends ContactAccessor{
+ public Intent getViewContactIntent() {
+ return new Intent();
+ }
+
+ @Override
+ public void viewContact(Context mContext, String number) {
+ //
+ }
+
+ @Override
+ public Intent getAddToContactIntent(String number) {
+
+ return null;
+ }
+}
diff --git a/src/roman10reborn/apl/main/Main.java b/src/roman10reborn/apl/main/Main.java
new file mode 100644
index 0000000..7ad0636
--- /dev/null
+++ b/src/roman10reborn/apl/main/Main.java
@@ -0,0 +1,1351 @@
+package roman10reborn.apl.main;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+
+import roman10reborn.apl.data2.AdvancedPhoneLogRecord;
+import roman10reborn.apl.main.R;
+import roman10reborn.dialogs.CallLogFilterDialog;
+import roman10reborn.dialogs.FilterNameListDialog;
+import roman10reborn.dialogs.FilterNumberListDialog;
+import roman10reborn.dialogs.MainChoiceDialog;
+import roman10reborn.expandableiconifiedlist.ExpandableThreeLinesIconifiedText;
+import roman10reborn.expandableiconifiedlist.ExpandableThreeLinesIconifiedTextChildView;
+import roman10reborn.expandableiconifiedlist.ExpandableThreeLinesIconifiedTextGroupView;
+import roman10reborn.expandableiconifiedlist.ExpandableThreeLinesIconifiedTextListAdapter;
+import roman10reborn.quickactionwindow.ActionItem;
+import roman10reborn.quickactionwindow.QuickAction;
+import roman10reborn.quickactionwindow.QuickAction2;
+import roman10reborn.threelinesiconifiedlist.ThreeLinesIconifiedText;
+import roman10reborn.utils.ConstantStatic;
+import roman10reborn.utils.ContactsHelperStatic;
+import roman10reborn.utils.SortingUtilsStatic;
+import roman10reborn.utils.TimeUtilsStatic;
+import android.R.color;
+import android.app.AlertDialog;
+import android.app.ExpandableListActivity;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.text.ClipboardManager;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.Button;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ExpandableListView.OnGroupClickListener;
+import android.widget.ExpandableListView.OnGroupCollapseListener;
+import android.widget.ExpandableListView.OnGroupExpandListener;
+import android.widget.PopupWindow.OnDismissListener;
+
+public class Main extends ExpandableListActivity implements ListView.OnScrollListener {
+ private static final String TAG = "Main";
+ private Button Btn_shortcut;
+ private Button Btn_sort;
+ private Button Btn_filter;
+ private Button Btn_delete;
+ private Context mContext;
+ private TextView text_total, text_empty;
+
+ private int lastListViewPos = 0;
+
+ public static final int SHORTCUT_ALL = 0;
+ public static final int SHORTCUT_ALL_MISSED = 1;
+ public static final int SHORTCUT_ALL_INCOMING = 2;
+ public static final int SHORTCUT_ALL_OUTGOING = 3;
+ public static final int SHORTCUT_ALL_CURRENT_MONTH = 4;
+ public static final int SHORTCUT_ALL_PREVIOUS_MONTH = 5;
+ private int last_shortcut_option = SHORTCUT_ALL;
+
+ public static final int SORT_DATE_DES = 0;
+ public static final int SORT_DATE_ASC = 1;
+ public static final int SORT_NAME_DES = 2;
+ public static final int SORT_NAME_ASC = 3;
+ public static final int SORT_DURATION_DES = 4;
+ public static final int SORT_DURATION_ASC = 5;
+ private int last_sort_option = SORT_DATE_DES;
+
+ private static final int REQUEST_FILTER_OPTION = 1;
+ private static final int REQUEST_ADD_TO_CONTACT = 2;
+ private static final int REQUEST_MAIN_OPTIONS = 3;
+ public static final String MAIN_OPTOINS_CHOICE = "main_option_result";
+
+ public static int total_missCallNum = 0, total_outCallNum = 0, total_inCallNum = 0, total_outCallTime = 0, total_inCallTime = 0;
+
+ //for making phone call and send out sms
+ public static String currentPhoneNumber = "";
+ public static String currentName = "";
+
+ private static int sdk;
+
+ private static int isFiltered = 0;
+
+ public static Main self;
+
+ public static ArrayList recordList = new ArrayList();
+ private static ArrayList filteredList = new ArrayList();
+ //private ArrayList viewList = new ArrayList();
+ private ArrayList viewGroupList = new ArrayList();
+ private ArrayList> viewList = new ArrayList>();
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = this.getApplicationContext();
+ self = this;
+ sdk = Integer.parseInt(Build.VERSION.SDK);
+ //start background service
+ //startAdvancedPhoneLogService();
+ setContentView(R.layout.main);
+ text_total = (TextView) findViewById(R.id.apl_main_total_text);
+ //text_total.setBackgroundResource(android.R.drawable.title_bar);
+ text_total.setBackgroundColor(color.darker_gray);
+ text_total.setTextColor(Color.WHITE);
+ text_total.setText("Advanced Phone Log");
+
+ //set up button events and UI
+ int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth();
+ Btn_shortcut = (Button) findViewById(R.id.apl_main_multi_btn_first);
+ Btn_shortcut.setWidth(screenWidth/4);
+ //Btn_shortcut.setBackgroundColor(R.color.custom_gray);
+ Btn_shortcut.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ final CharSequence[] SHORTCUT_OPTIONS = {"All Logs", "All Missed Call",
+ "All Incoming", "All Outgoing", "Current Month Logs",
+ "Previous Month Logs"
+ };
+ AlertDialog.Builder l_builder = new AlertDialog.Builder(Main.this);
+ l_builder.setTitle("Choose a Shortcut");
+ l_builder.setSingleChoiceItems(SHORTCUT_OPTIONS, last_shortcut_option, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ boolean l_typeFilter = false, l_startTimeFilter = false;
+ boolean l_endTimeFilter = false;;
+ boolean l_nameFilter = false, l_numberFilter = false;
+ switch (which) {
+ case SHORTCUT_ALL:
+ isFiltered = 0;
+ break;
+ case SHORTCUT_ALL_MISSED:
+ l_typeFilter = true;
+ CallLogFilterDialog.filter_callType = CallLogFilterDialog.FILTER_CALLTYPE_MISSED;
+ isFiltered = 1;
+ break;
+ case SHORTCUT_ALL_INCOMING:
+ l_typeFilter = true;
+ CallLogFilterDialog.filter_callType = CallLogFilterDialog.FILTER_CALLTYPE_IN;
+ isFiltered = 1;
+ break;
+ case SHORTCUT_ALL_OUTGOING:
+ l_typeFilter = true;
+ CallLogFilterDialog.filter_callType = CallLogFilterDialog.FILTER_CALLTYPE_OUT;
+ isFiltered = 1;
+ break;
+ case SHORTCUT_ALL_CURRENT_MONTH:
+ l_startTimeFilter = true;
+ final Calendar c = Calendar.getInstance();
+ CallLogFilterDialog.startYear = c.get(Calendar.YEAR);
+ CallLogFilterDialog.startMonth = c.get(Calendar.MONTH);
+ CallLogFilterDialog.startDay = c.getActualMinimum(Calendar.DATE);
+ isFiltered = 1;
+ break;
+ case SHORTCUT_ALL_PREVIOUS_MONTH:
+ l_startTimeFilter = true;
+ final Calendar l_c = Calendar.getInstance();
+ CallLogFilterDialog.startMonth = l_c.get(Calendar.MONTH) - 1;
+ if (CallLogFilterDialog.startMonth < 0) {
+ CallLogFilterDialog.startMonth = 11;
+ CallLogFilterDialog.startYear = l_c.get(Calendar.YEAR) - 1;
+ } else {
+ CallLogFilterDialog.startYear = l_c.get(Calendar.YEAR);
+ }
+ CallLogFilterDialog.startDay = l_c.getActualMinimum(Calendar.DATE);
+ l_endTimeFilter = true;
+ CallLogFilterDialog.endMonth = l_c.get(Calendar.MONTH) - 1;
+ if (CallLogFilterDialog.endMonth < 0) {
+ CallLogFilterDialog.endMonth = 11;
+ CallLogFilterDialog.endYear = l_c.get(Calendar.YEAR) - 1;
+ } else {
+ CallLogFilterDialog.endYear = l_c.get(Calendar.YEAR);
+ }
+ CallLogFilterDialog.endDay = l_c.getActualMaximum(Calendar.DATE);
+ isFiltered = 1;
+ break;
+ default:
+ isFiltered = 0;
+ break;
+ }
+ last_shortcut_option = which;
+ dialog.dismiss();
+ if (isFiltered == 0) {
+ convertRecordToExpandableDisplayData(recordList);
+ } else {
+ filteredList = filterPhoneLogs(recordList, l_typeFilter, l_startTimeFilter,
+ l_endTimeFilter, l_nameFilter, l_numberFilter);
+ convertRecordToExpandableDisplayData(filteredList);
+ }
+ refreshUI();
+ }
+ });
+ AlertDialog l_shortcut = l_builder.create();
+ l_shortcut.show();
+ }
+ });
+ Btn_sort = (Button) findViewById(R.id.apl_main_multi_btn_second);
+ Btn_sort.setWidth(screenWidth/4);
+ Btn_sort.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ final CharSequence[] SORT_OPTIONS = {"Sort by Date Des", "Sort by Date Asc", "Sort by Name Des", "Sort by Name Asc",
+ "Sort by Talk Time Des", "Sort by Talk Time Asc" };
+ AlertDialog.Builder l_builder = new AlertDialog.Builder(Main.this);
+ l_builder.setTitle("Choose an Option");
+ l_builder.setSingleChoiceItems(SORT_OPTIONS, last_sort_option, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case SORT_DATE_DES:
+ if (isFiltered == 0) {
+ SortingUtilsStatic.sortRecordsByDateDesc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByDateDesc(filteredList);
+ }
+ break;
+ case SORT_DATE_ASC:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByDateAsc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByDateAsc(filteredList);
+ }
+ break;
+ case SORT_NAME_DES:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByNameDesc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByNameDesc(filteredList);
+ }
+ break;
+ case SORT_NAME_ASC:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByNameAsc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByNameAsc(filteredList);
+ }
+ break;
+ case SORT_DURATION_DES:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByDurationDesc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByDurationDesc(filteredList);
+ }
+ break;
+ case SORT_DURATION_ASC:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByDurationAsc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByDurationAsc(filteredList);
+ }
+ break;
+ default:
+ if (isFiltered==0) {
+ SortingUtilsStatic.sortRecordsByDateDesc(recordList);
+ } else {
+ SortingUtilsStatic.sortRecordsByDateDesc(filteredList);
+ }
+ break;
+ }
+ last_sort_option = which;
+ dialog.dismiss();
+ //viewList = convertRecordToDisplayData(recordList);
+ if (isFiltered == 0) {
+ convertRecordToExpandableDisplayData(recordList);
+ } else {
+ convertRecordToExpandableDisplayData(filteredList);
+ }
+ refreshUI();
+ }
+ });
+ AlertDialog l_option = l_builder.create();
+ l_option.show();
+ }
+ });
+ Btn_filter = (Button) findViewById(R.id.apl_main_multi_btn_third);
+ Btn_filter.setWidth(screenWidth/4);
+ Btn_filter.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Intent l_intent = new Intent();
+ l_intent.setClass(mContext, roman10reborn.dialogs.CallLogFilterDialog.class);
+ startActivityForResult(l_intent, REQUEST_FILTER_OPTION);
+ }
+ });
+ Btn_delete = (Button) findViewById(R.id.apl_main_multi_btn_forth);
+ Btn_delete.setWidth(screenWidth/4);
+ Btn_delete.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //allow more options
+ createAdditionalMenu(v);
+ }
+ });
+
+ Btn_shortcut.setVisibility(View.GONE);
+ Btn_sort.setVisibility(View.GONE);
+ Btn_filter.setVisibility(View.GONE);
+ Btn_delete.setVisibility(View.GONE);
+
+ this.getExpandableListView().setOnGroupClickListener(new OnGroupClickListener(){
+ public boolean onGroupClick(ExpandableListView arg0, View arg1,
+ int groupPosition, long arg3) {
+ groupOrChildClick = 0;
+ currentGroupPos = groupPosition;
+ if (getExpandableListAdapter().getChildrenCount(groupPosition)==0) {
+ askForAnOption();
+ }
+// if (getExpandableListAdapter().getChildrenCount(groupPosition)==0) {
+// currentPhoneNumber = viewGroupList.get(groupPosition).getTextLine2();
+// currentName = viewGroupList.get(groupPosition).getTextLine1Text1();
+// if ((currentPhoneNumber!=null) && (currentPhoneNumber.compareTo("-1")!=0) && (!currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+// popupQuickAction(arg1);
+// }
+// }
+ return false;
+ }
+
+ });
+
+ this.getExpandableListView().setLongClickable(true);
+ this.getExpandableListView().setOnItemLongClickListener(new OnItemLongClickListener() {
+ public boolean onItemLongClick(AdapterView> arg0, View arg1,
+ int arg2, long arg3) {
+ //askForAnOption();
+ return false;
+ }
+ });
+
+ this.getExpandableListView().setOnGroupExpandListener(new OnGroupExpandListener() {
+ public void onGroupExpand(int groupPosition) {
+ //
+
+ }
+ });
+
+ this.getExpandableListView().setOnGroupCollapseListener(new OnGroupCollapseListener() {
+ public void onGroupCollapse(int groupPosition) {
+ //
+
+ }
+ });
+
+ recordList = getAllCallLogs();
+ //viewList = convertRecordToDisplayData(recordList);
+ isFiltered = 0;
+ convertRecordToExpandableDisplayData(recordList);
+ refreshUI();
+ }
+
+ private void askForAnOption() {
+ Intent l_intent = new Intent();
+ l_intent.setClass(mContext, roman10reborn.dialogs.MainChoiceDialog.class);
+ startActivityForResult(l_intent, REQUEST_MAIN_OPTIONS);
+ }
+
+ private void refreshData() {
+ recordList = getAllCallLogs();
+ isFiltered = 0;
+ convertRecordToExpandableDisplayData(recordList);
+ }
+
+ private void refreshUI() {
+ //set up the list view
+ //ThreeLinesIconifiedTextListAdapter adapter = new ThreeLinesIconifiedTextListAdapter(this);
+ //ExpandableThreeLinesIconifiedTextListAdapter adapter = new ExpandableThreeLinesIconifiedTextListAdapter(this);
+ SlowAdapter adapter = new SlowAdapter(this);
+ StringBuilder l_builder = new StringBuilder();
+ //l_builder.append("Advanced Phone Log\n");
+ l_builder.append("Miss: ").append(total_missCallNum).append("; ");
+ l_builder.append("Out: ").append(total_outCallNum).append("; ");
+ l_builder.append("In: ").append(total_inCallNum).append("\n");
+ String l_talkTime = String.format("%02d:%02d:%02d", total_outCallTime/3600, (total_outCallTime%3600)/60,(total_outCallTime%3600)%60);
+ l_builder.append("OT: ").append(l_talkTime).append("; ");
+ l_talkTime = String.format("%02d:%02d:%02d", total_inCallTime/3600,
+ (total_inCallTime%3600)/60,(total_inCallTime%3600)%60);
+ l_builder.append("IT: ").append(l_talkTime).append("; ");
+ l_talkTime = String.format("%02d:%02d:%02d",
+ (total_inCallTime+total_outCallTime)/3600,
+ ((total_inCallTime+total_outCallTime)%3600)/60,
+ ((total_inCallTime+total_outCallTime)%3600)%60);
+ l_builder.append("TT: ").append(l_talkTime).append("\n");
+
+ text_total.setText(l_builder.toString());
+
+ text_empty = (TextView) findViewById(R.id.apl_main_empty_text);
+ if ((viewList.size()==0) && (viewGroupList.size()==0)) {
+ text_empty.setTextColor(Color.WHITE);
+ text_empty.setVisibility(View.VISIBLE);
+ text_empty.setText("Phone Log is Empty!");
+ } else {
+ text_empty.setVisibility(View.GONE);
+ }
+
+ adapter.setListItems(viewList);
+ adapter.setGroups(viewGroupList);
+ if (viewGroupList.size() > 30) {
+ getExpandableListView().setFastScrollEnabled(true);
+ } else {
+ getExpandableListView().setFastScrollEnabled(false);
+ }
+ this.getExpandableListView().setGroupIndicator(null);
+ this.setListAdapter(adapter);
+ this.getExpandableListView().setOnScrollListener(this);
+ if (lastListViewPos < adapter.getGroupCount()) {
+ this.getExpandableListView().setSelection(lastListViewPos);
+ } else {
+ this.getExpandableListView().setSelection(adapter.getGroupCount()-1);
+ }
+ }
+
+
+ public void onScroll(AbsListView view, int firstVisibleItem,
+ int visibleItemCount, int totalItemCount) {
+ lastListViewPos = firstVisibleItem;
+ }
+
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ switch (scrollState) {
+ case OnScrollListener.SCROLL_STATE_IDLE:
+ int l_first = view.getFirstVisiblePosition();
+ int l_count = view.getChildCount();
+ for (int i = 0; i < l_count; ++i) {
+ AttachedTag l_at = (AttachedTag)view.getChildAt(i).getTag();
+ if (l_at.groupOrChild==0) {
+ ExpandableThreeLinesIconifiedTextGroupView l_groupView =
+ (ExpandableThreeLinesIconifiedTextGroupView)view.getChildAt(i);
+ if (l_at.photoLoaded==0) {
+ Drawable l_photo = getPhotoDrawable(viewGroupList.get(l_first+i).getTextLine2());
+ //l_groupView.getContent().setLeftIcon(l_photo);
+ viewGroupList.get(l_first+i).setLeftIcon(l_photo);
+ int l_size = viewList.get(l_first+i).size();
+ for (int j = 0; j < l_size; ++j) {
+ viewList.get(l_first+i).get(j).setLeftIcon(l_photo);
+ }
+ l_groupView.setLeftIcon(l_photo);
+ l_at.photoLoaded = 1;
+ l_groupView.setTag(l_at);
+ }
+ }
+ }
+ break;
+ case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
+ break;
+ case OnScrollListener.SCROLL_STATE_FLING:
+ break;
+ }
+ }
+
+ private class AttachedTag {
+ public int groupOrChild; //0 for group, 1 for child
+ public int photoLoaded;
+ public AttachedTag(int _groupOrChild, int _photoLoaded){
+ groupOrChild = _groupOrChild;
+ photoLoaded = _photoLoaded;
+ }
+ }
+
+ /**
+ *
+ * SlowAdapter
+ */
+ /**
+ * Will not bind views while the list is scrolling
+ *
+ */
+ private class SlowAdapter extends BaseExpandableListAdapter {
+ private Context mContext;
+
+ private ArrayList> mItems = new ArrayList>();
+ private ArrayList mGroups = new ArrayList();
+
+ public SlowAdapter(Context context) {
+ mContext = context;
+ }
+
+ public void setListItems(ArrayList> lit)
+ { mItems = lit; }
+
+ public void setGroups(ArrayList _groups) {
+ mGroups = _groups;
+ }
+
+
+ public Object getChild(int arg0, int arg1) {
+ return mItems.get(arg0).get(arg1);
+ }
+
+ public long getChildId(int arg0, int arg1) {
+ long id = 0;
+ for (int i = 0; i < arg0; ++i) {
+ id += mItems.get(i).size();
+ }
+ return id + arg1;
+ }
+
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
+ ViewGroup parent) {
+ ExpandableThreeLinesIconifiedTextChildView btv;
+ int l_photoLoaded = 0;
+ if (convertView == null) {
+ btv = new ExpandableThreeLinesIconifiedTextChildView(mContext, mItems.get(groupPosition).get(childPosition));
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (ExpandableThreeLinesIconifiedTextChildView) convertView;
+ btv.setTextLine1Text1(mItems.get(groupPosition).get(childPosition).getTextLine1Text1());
+ btv.setTextLine1Text2("");
+ btv.setTextLine2(mItems.get(groupPosition).get(childPosition).getTextLine2());
+ /*set week of day as bold to separate the time*/
+ SpannableStringBuilder lSpanStr = new SpannableStringBuilder(mItems.get(groupPosition).get(childPosition).getTextLine3());
+ lSpanStr.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 10, 13, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ btv.setTextLine3(lSpanStr, TextView.BufferType.SPANNABLE);
+
+ btv.setLeftIconText(mItems.get(groupPosition).get(childPosition).getLeftIconText());
+ btv.setRightIconText(mItems.get(groupPosition).get(childPosition).getRightIconText());
+ btv.setRightIcon(mItems.get(groupPosition).get(childPosition).getRightIcon());
+ }
+ btv.mRightIcon.setTag(groupPosition + " " + childPosition);
+ btv.mRightIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //call the number
+ String l_pos = (String)v.getTag();
+ int l_emptyPos = l_pos.indexOf(" ");
+ int l_groupPos = Integer.parseInt(l_pos.substring(0, l_emptyPos));
+ int l_childPos = Integer.parseInt(l_pos.substring(l_emptyPos + 1, l_pos.length()));
+ makeACall(mItems.get(l_groupPos).get(l_childPos).getTextLine2());
+ }
+ });
+ Drawable l_leftIcon = mItems.get(groupPosition).get(childPosition).getLeftIcon();
+ if (l_leftIcon==null) {
+ btv.setLeftIcon(R.drawable.ic_contact_list_picture);
+ l_photoLoaded = 0;
+ } else {
+ btv.setLeftIcon(l_leftIcon);
+ l_photoLoaded = 1;
+ }
+ btv.mLeftIcon.setTag(groupPosition + " " + childPosition);
+ btv.mLeftIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ String l_pos = (String)v.getTag();
+ int l_emptyPos = l_pos.indexOf(" ");
+ int l_groupPos = Integer.parseInt(l_pos.substring(0, l_emptyPos));
+ int l_childPos = Integer.parseInt(l_pos.substring(l_emptyPos + 1, l_pos.length()));
+ Main.currentPhoneNumber = mItems.get(l_groupPos).get(l_childPos).getTextLine2();
+ Main.currentName = mGroups.get(l_groupPos).getTextLine1Text1();
+ if ((Main.currentPhoneNumber!=null) && (Main.currentPhoneNumber.compareTo("-1")!=0) && (!Main.currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+ popupQuickAction(v);
+ }
+ }
+ });
+ btv.setTag(new AttachedTag(1, l_photoLoaded));
+ return btv;
+ }
+
+ public int getChildrenCount(int groupPosition) {
+ return mItems.get(groupPosition).size();
+ }
+
+ public Object getGroup(int groupPosition) {
+ return mItems.get(groupPosition);
+ }
+
+ public int getGroupCount() {
+ return mItems.size();
+ }
+
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ public View getGroupView(int groupPosition, boolean isExpanded,
+ View convertView, ViewGroup parent) {
+ ExpandableThreeLinesIconifiedTextGroupView btv;
+ int l_photoLoaded = 0;
+ if (convertView == null) {
+ btv = new ExpandableThreeLinesIconifiedTextGroupView(mContext, mGroups.get(groupPosition));
+ if(getChildrenCount(groupPosition)==0) {
+ btv.setFillerWidth(1);
+ } else {
+ btv.setFillerWidth(2);
+ }
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (ExpandableThreeLinesIconifiedTextGroupView) convertView;
+ btv.setTextLine1Text1(mGroups.get(groupPosition).getTextLine1Text1());
+ btv.setTextLine1Text2(mGroups.get(groupPosition).getTextLine1Text2());
+ btv.setTextLine2(mGroups.get(groupPosition).getTextLine2());
+
+ SpannableStringBuilder lSpanStr = new SpannableStringBuilder(mGroups.get(groupPosition).getTextLine3());
+ lSpanStr.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 10, 13, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ btv.setTextLine3(lSpanStr, TextView.BufferType.SPANNABLE);
+
+ //btv.setTextLine3(mGroups.get(groupPosition).getTextLine3());
+ //btv.setLeftIconText(mGroups.get(groupPosition).getLeftIconText());
+ btv.setRightIconText(mGroups.get(groupPosition).getRightIconText());
+ if (isExpanded) {
+ btv.setRightIcon(mGroups.get(groupPosition).getRightIcon2());
+ } else {
+ btv.setRightIcon(mGroups.get(groupPosition).getRightIcon1());
+ }
+ if(getChildrenCount(groupPosition)==0) {
+ btv.setFillerWidth(1);
+ } else {
+ btv.setFillerWidth(2);
+ }
+ }
+ btv.mRightIcon.setTag(groupPosition);
+ btv.mRightIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //call the number
+ int l_groupPos = (Integer)v.getTag();
+ makeACall(mGroups.get(l_groupPos).getTextLine2());
+ }
+ });
+ //photo is not loaded yet
+ Drawable l_leftIcon = mGroups.get(groupPosition).getLeftIcon();
+ if (l_leftIcon==null) {
+ btv.setLeftIcon(R.drawable.ic_contact_list_picture);
+ l_photoLoaded = 0;
+ } else {
+ btv.setLeftIcon(l_leftIcon);
+ l_photoLoaded = 1;
+ }
+ btv.mLeftIcon.setTag(groupPosition);
+ btv.mLeftIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_groupPos = (Integer)v.getTag();
+ Main.currentPhoneNumber = mGroups.get(l_groupPos).getTextLine2();
+ Main.currentName = mGroups.get(l_groupPos).getTextLine1Text1();
+ if ((Main.currentPhoneNumber!=null) && (Main.currentPhoneNumber.compareTo("-1")!=0) && (!Main.currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+ popupQuickAction(v);
+ }
+ }
+ });
+ btv.setTag(new AttachedTag(0, l_photoLoaded));
+ return btv;
+ }
+
+ private void popupQuickAction(View v) {
+ final QuickAction mQuickAction = new QuickAction(v);
+ final ActionItem phoneAction = new ActionItem();
+ phoneAction.setTitle("Call");
+ phoneAction.setIcon(mContext.getResources().getDrawable(R.drawable.phonecall1));
+ final ActionItem smsAction = new ActionItem();
+ smsAction.setTitle("SMS");
+ smsAction.setIcon(mContext.getResources().getDrawable(R.drawable.sms1));
+ final ActionItem contactAction = new ActionItem();
+ if (!Main.currentName.contains(ConstantStatic.UNKNOWN)) {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.viewcontact2));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //view contact
+ viewContact(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ } else {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.addcontact));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //add phone number to contact
+ Main.addToContact(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ }
+
+ phoneAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Main.makeAPhoneCall(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ smsAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Main.sendOutSms(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ mQuickAction.addActionItem(phoneAction);
+ mQuickAction.addActionItem(smsAction);
+ if (Integer.parseInt(Build.VERSION.SDK) >= Build.VERSION_CODES.ECLAIR) {
+ mQuickAction.addActionItem(contactAction);
+ }
+ //mQuickAction.addActionItem(deleteAction);
+ mQuickAction.setAnimStyle(QuickAction.ANIM_GROW_FROM_RIGHT);
+ mQuickAction.setOnDismissListener(new OnDismissListener(){
+ public void onDismiss() {
+ //do nothing
+ }
+ });
+ mQuickAction.show();
+ }
+
+ //sdk dependent
+ private void viewContact(String _number) {
+ ContactAccessor.getInstance().viewContact(mContext, _number);
+ }
+
+ private void makeACall(String _number) {
+ try {
+ Intent callIntent = new Intent(Intent.ACTION_CALL);
+ callIntent.setData(Uri.parse("tel:" + _number));
+ mContext.startActivity(callIntent);
+ } catch (ActivityNotFoundException e) {
+ //
+ }
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return mItems.get(groupPosition).get(childPosition).isSelectable();
+ }
+ }
+
+
+ private void createAdditionalMenu(View _v) {
+ final ActionItem first = new ActionItem();
+
+ first.setTitle("Share this App");
+ //first.setIcon(getResources().getDrawable(R.drawable.ic_accept));
+ first.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ shareTheApp();
+ //Toast.makeText(Main.this, "Share this App" , Toast.LENGTH_SHORT).show();
+ }
+ });
+
+
+ final ActionItem second = new ActionItem();
+ second.setTitle("Request a Feature");
+ //second.setIcon(getResources().getDrawable(R.drawable.ic_add));
+ second.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ sendEmailToRequestAFeature();
+ //Toast.makeText(Main.this, "Request a feature", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ final ActionItem third = new ActionItem();
+ third.setTitle("Report a Bug");
+ third.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ sendEmailToReportABug();
+ //Toast.makeText(Main.this, "Request ", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ final ActionItem forth = new ActionItem();
+ forth.setTitle("Get TS II");
+ forth.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ getTS2();
+ }
+ });
+
+ final QuickAction2 l_qa = new QuickAction2(_v);
+ l_qa.addActionItem(first);
+ l_qa.addActionItem(second);
+ l_qa.addActionItem(third);
+ l_qa.addActionItem(forth);
+ l_qa.show();
+ }
+
+ private Drawable getPhotoDrawable(String _number) {
+ Drawable l_drawable;
+ long l_contactId = ContactsHelperStatic.getContactIdByPhoneNumber(mContext, _number);
+ l_drawable = ContactsHelperStatic.getContactsPhotoDrawable(mContext, l_contactId);
+ if (l_drawable == null) {
+ return mContext.getResources().getDrawable(R.drawable.ic_contact_list_picture);
+ } else {
+ return l_drawable;
+ }
+ }
+ private static final int INIT_NUM_OF_PHOTOS = 8;
+ private void convertRecordToExpandableDisplayData(ArrayList _recordList) {
+ viewList.clear(); viewGroupList.clear();
+ total_missCallNum = 0; total_outCallNum = 0; total_inCallNum = 0;
+ total_outCallTime = 0; total_inCallTime = 0;
+ ArrayList l_aGroup = null;
+ Drawable l_defaultGroupIndicator1 = mContext.getResources().getDrawable(R.drawable.arrowleft);
+ Drawable l_defaultGroupIndicator2 = mContext.getResources().getDrawable(R.drawable.arrowdown);
+ int l_recordSize = _recordList.size();
+ AdvancedPhoneLogRecord l_record = null;
+ Drawable l_photoIcon = null;
+ int l_numOfPhotos = 0;
+ String l_lastNumber = "";
+ for (int i = 0; i < l_recordSize; ++i) {
+ l_record = _recordList.get(i);
+ String l_line1 = ((l_record.aplr_name==null) || (l_record.aplr_name.compareTo("") == 0)) ? ConstantStatic.UNKNOWN : l_record.aplr_name;
+ String l_line2 = l_record.aplr_number.compareTo("-1")==0?ConstantStatic.NOTAVAIL : l_record.aplr_number;
+ String l_line3 = TimeUtilsStatic.dateToStringFormat2(l_record.aplr_time);
+ String l_iconText = String.format("%02d:%02d", l_record.aplr_duration/60, l_record.aplr_duration%60);
+ Drawable l_drawable = null;
+ switch (l_record.aplr_type) {
+ case android.provider.CallLog.Calls.INCOMING_TYPE:
+ l_drawable = this.getResources().getDrawable(android.R.drawable.sym_call_incoming);
+ ++total_inCallNum;
+ total_inCallTime += l_record.aplr_duration;
+ break;
+ case android.provider.CallLog.Calls.OUTGOING_TYPE:
+ l_drawable = this.getResources().getDrawable(android.R.drawable.sym_call_outgoing);
+ ++total_outCallNum;
+ total_outCallTime += l_record.aplr_duration;
+ break;
+ case android.provider.CallLog.Calls.MISSED_TYPE:
+ l_drawable = this.getResources().getDrawable(android.R.drawable.sym_call_missed);
+ ++total_missCallNum;
+ break;
+ }
+ //photo icon only needs to change when there is a new number
+ if (l_record.aplr_number.compareTo(l_lastNumber)!=0) {
+ l_lastNumber = l_record.aplr_number;
+ if (l_numOfPhotos < INIT_NUM_OF_PHOTOS) {
+ l_photoIcon = getPhotoDrawable(l_record.aplr_number);
+ ++l_numOfPhotos;
+ } else {
+ l_photoIcon = null;
+ }
+ }
+
+ //l_anItem = new ExpandableThreeLinesIconifiedText(l_iconText, l_iconText, l_line1, "", l_line2, l_line3, l_drawable, l_record.aplr_number.compareTo("-1")==0?null:l_callIcon);
+ ExpandableThreeLinesIconifiedText l_anItem = new ExpandableThreeLinesIconifiedText("", l_iconText, l_line1,
+ "", l_line2, l_line3, l_photoIcon, l_drawable, l_record.aplr_id,
+ l_record);
+ //first record, create new group
+ if (i == 0) {
+ l_aGroup = new ArrayList();
+ l_aGroup.add(l_anItem);
+ continue;
+ }
+ if (l_record.isSameContact(_recordList.get(i-1))) {
+ //same as last record, do not create new group
+ l_aGroup.add(l_anItem);
+ } else {
+ //a new record, add old group to viewList, create new group
+ int l_size = l_aGroup.size();
+ if (l_size==1) {
+ //[workaround]empty list, so it won't expand
+ viewList.add(new ArrayList());
+ } else {
+ viewList.add(l_aGroup);
+ }
+ ExpandableThreeLinesIconifiedText l_topRecord = l_aGroup.get(0);
+ viewGroupList.add(new ExpandableThreeLinesIconifiedText(
+ l_topRecord.getLeftIconText(),
+ l_topRecord.getRightIconText(),
+ l_topRecord.getTextLine1Text1(), l_size==1?"":String.valueOf(l_size),
+ l_topRecord.getTextLine2(), l_topRecord.getTextLine3(),
+ l_topRecord.getLeftIcon(),
+ l_size==1?l_topRecord.getRightIcon():l_defaultGroupIndicator1,
+ l_size==1?l_topRecord.getRightIcon():l_defaultGroupIndicator2,
+ l_topRecord.getId(),
+ l_topRecord.getAPL()));
+
+ l_aGroup = new ArrayList();
+ l_aGroup.add(l_anItem);
+ }
+ }
+ //add the last group and its children
+ if (l_recordSize > 0) {
+ int l_size = l_aGroup.size();
+ if (l_size==1) {
+ //[workaround]empty list, so it won't expand
+ viewList.add(new ArrayList());
+ } else {
+ viewList.add(l_aGroup);
+ }
+ ExpandableThreeLinesIconifiedText l_topRecord = l_aGroup.get(0);
+ viewGroupList.add(new ExpandableThreeLinesIconifiedText(
+ l_topRecord.getLeftIconText(),
+ l_topRecord.getRightIconText(),
+ l_topRecord.getTextLine1Text1(),
+ l_size==1?"":String.valueOf(l_size),
+ l_topRecord.getTextLine2(), l_topRecord.getTextLine3(),
+ l_topRecord.getLeftIcon(),
+ l_size==1?l_topRecord.getRightIcon():l_defaultGroupIndicator1,
+ l_size==1?l_topRecord.getRightIcon():l_defaultGroupIndicator2,
+ l_topRecord.getId(),
+ l_topRecord.getAPL()));
+ }
+ }
+
+ //get all the call logs sorted by date
+ private ArrayList getAllCallLogs() {
+ ArrayList l_list = new ArrayList();
+ //query all all call logs
+ Cursor l_cur = mContext.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI,
+ null, null, null, android.provider.CallLog.Calls.DATE + " DESC");
+ this.startManagingCursor(l_cur);
+
+ //retrieve the information: number, name, time, type
+ int l_idCol = l_cur.getColumnIndex(android.provider.CallLog.Calls._ID);
+ int l_numberCol = l_cur.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
+ int l_nameCol = l_cur.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);
+ int l_timeCol = l_cur.getColumnIndex(android.provider.CallLog.Calls.DATE);
+ int l_typeCol = l_cur.getColumnIndex(android.provider.CallLog.Calls.TYPE);
+ int l_durationCol = l_cur.getColumnIndex(android.provider.CallLog.Calls.DURATION);
+ int l_logCount = 0;
+ if (l_cur.moveToFirst()) {
+ do {
+ String l_number = l_cur.getString(l_numberCol);
+ String l_name = l_cur.getString(l_nameCol);
+ Date l_time = new Date(l_cur.getLong(l_timeCol));
+ int l_type = l_cur.getInt(l_typeCol);
+ int l_duration = l_cur.getInt(l_durationCol);
+ int l_id = l_cur.getInt(l_idCol);
+ l_list.add(new AdvancedPhoneLogRecord(l_number, l_name, l_time,
+ l_type, l_duration, l_id, l_logCount));
+ ++l_logCount;
+ } while (l_cur.moveToNext());
+ }
+
+ return l_list;
+ }
+
+ private ArrayList filterPhoneLogs(ArrayList _records,
+ boolean _typeFilter, boolean _startTimeFilter, boolean _endTimeFilter,
+ boolean _nameFilter, boolean _numberFilter) {
+ ArrayList l_list = new ArrayList();
+ for (int i = 0; i < _records.size(); ++i) {
+ AdvancedPhoneLogRecord l_aRecord = _records.get(i);
+ //call type
+ if (_typeFilter) {
+ if ((CallLogFilterDialog.filter_callType!=CallLogFilterDialog.FILTER_CALLTYPE_ALL) &&
+ (l_aRecord.aplr_type != CallLogFilterDialog.filter_callType)) {
+ continue;
+ }
+ }
+ //start time and end time
+ if (_startTimeFilter) {
+ Date l_startTime = new Date(CallLogFilterDialog.startYear-1900, CallLogFilterDialog.startMonth, CallLogFilterDialog.startDay, 0, 0, 0);
+ if (l_aRecord.aplr_time.before(l_startTime)) {
+ continue;
+ }
+ }
+ if (_endTimeFilter) {
+ Date l_endTime = new Date(CallLogFilterDialog.endYear-1900, CallLogFilterDialog.endMonth, CallLogFilterDialog.endDay, 23, 59, 59);
+ if (l_aRecord.aplr_time.after(l_endTime)) {
+ continue;
+ }
+ }
+ int l_cnt, j;
+ //name
+ if (_nameFilter) {
+ l_cnt = FilterNameListDialog.selectedNamesList.size();
+ j = 0;
+ for (; j < l_cnt; ++j) {
+ if (l_aRecord.aplr_name == null) {
+ j = l_cnt-1; continue;
+ }
+ if (FilterNameListDialog.selectedNamesList.get(j).compareToIgnoreCase(l_aRecord.aplr_name)==0) {
+ break;
+ }
+ }
+ if ((l_cnt!=0) && (j==l_cnt))
+ continue;
+ }
+ //number
+ if (_numberFilter) {
+ l_cnt = FilterNumberListDialog.selectedNumbersList.size();
+ for (j = 0; j < l_cnt; ++j) {
+ if (FilterNumberListDialog.selectedNumbersList.get(j).compareToIgnoreCase(l_aRecord.aplr_number)==0) {
+ break;
+ }
+ }
+ if ((l_cnt!=0) && (j==l_cnt))
+ continue;
+ }
+ //passed all the test
+ l_list.add(l_aRecord);
+ }
+ return l_list;
+ }
+
+ public static void makeAPhoneCall(String _number) {
+ //
+ if (_number.contains(ConstantStatic.NOTAVAIL)) {
+ return;
+ } else {
+ String l_url = "tel:" + _number;
+ Intent l_intent = new Intent(Intent.ACTION_DIAL, Uri.parse(l_url));
+ self.startActivity(l_intent);
+ }
+ }
+
+ public static void sendOutSms(String _number) {
+ //
+ if (_number.contains(ConstantStatic.NOTAVAIL)) {
+ return;
+ } else {
+ String l_url = "smsto:" + _number;
+ Intent l_intent = new Intent(Intent.ACTION_VIEW, Uri.parse(l_url));
+ l_intent.setType("vnd.android-dir/mms-sms");
+ l_intent.putExtra("address", _number);
+ self.startActivity(l_intent);
+ }
+ }
+
+
+ //sdk dependent
+ private void viewContact(String _number) {
+ ContactAccessor.getInstance().viewContact(mContext, _number);
+ }
+ //sdk dependent
+ public static void addToContact(String _number) {
+ Intent l_intent = ContactAccessor.getInstance().getAddToContactIntent(_number);
+ self.startActivityForResult(l_intent, REQUEST_ADD_TO_CONTACT);
+ }
+
+ private void popupQuickAction(View v) {
+ final QuickAction mQuickAction = new QuickAction(v);
+ final ActionItem phoneAction = new ActionItem();
+ phoneAction.setTitle("Call");
+ phoneAction.setIcon(mContext.getResources().getDrawable(R.drawable.phonecall1));
+ final ActionItem smsAction = new ActionItem();
+ smsAction.setTitle("SMS");
+ smsAction.setIcon(mContext.getResources().getDrawable(R.drawable.sms1));
+ final ActionItem contactAction = new ActionItem();
+ if (!currentName.contains(ConstantStatic.UNKNOWN)) {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.viewcontact2));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //view contact
+ viewContact(currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ } else {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.addcontact));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //add phone number to contact
+ addToContact(currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ }
+// final ActionItem deleteAction = new ActionItem();
+// deleteAction.setTitle("Delete");
+// deleteAction.setIcon(mContext.getResources().getDrawable(R.drawable.delete));
+// deleteAction.setOnClickListener(new View.OnClickListener() {
+// public void onClick(View v) {
+// //delete the phone log
+//
+// }
+// });
+
+ phoneAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ makeAPhoneCall(currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ smsAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ sendOutSms(currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ mQuickAction.addActionItem(phoneAction);
+ mQuickAction.addActionItem(smsAction);
+ if (sdk >= Build.VERSION_CODES.ECLAIR) {
+ mQuickAction.addActionItem(contactAction);
+ }
+ //mQuickAction.addActionItem(deleteAction);
+ mQuickAction.setAnimStyle(QuickAction.ANIM_GROW_FROM_RIGHT);
+ mQuickAction.setOnDismissListener(new OnDismissListener(){
+ public void onDismiss() {
+ //do nothing
+ }
+ });
+ mQuickAction.show();
+ }
+
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+ //ExpandableThreeLinesIconifiedTextChildView childView = (ExpandableThreeLinesIconifiedTextChildView)v;
+ //currentPhoneNumber = childView.getContent().getTextLine2();
+// currentPhoneNumber = viewList.get(groupPosition).get(childPosition).getTextLine2();
+// currentName = viewGroupList.get(groupPosition).getTextLine1Text1();
+// if ((currentPhoneNumber!=null) && (currentPhoneNumber.compareTo("-1")!=0) && (!currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+// popupQuickAction(v);
+// }
+ groupOrChildClick = 1;
+ currentGroupPos = groupPosition;
+ currentChildPos = childPosition;
+ askForAnOption();
+ return false;
+ }
+
+
+ private static boolean menu_shown = false;
+ private void toggleVisibilityOfMenuButtons() {
+ if (menu_shown) {
+ menu_shown = false;
+ Btn_shortcut.setVisibility(View.GONE);
+ Btn_sort.setVisibility(View.GONE);
+ Btn_filter.setVisibility(View.GONE);
+ Btn_delete.setVisibility(View.GONE);
+ } else {
+ menu_shown = true;
+ Btn_shortcut.setVisibility(View.VISIBLE);
+ Btn_sort.setVisibility(View.VISIBLE);
+ Btn_filter.setVisibility(View.VISIBLE);
+ Btn_delete.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ toggleVisibilityOfMenuButtons();
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent i) {
+ super.onActivityResult(requestCode, resultCode, i);
+ switch (requestCode) {
+ case REQUEST_FILTER_OPTION:
+ //filtering options
+ if (resultCode == RESULT_OK) {
+ isFiltered = 1;
+ filteredList = filterPhoneLogs(recordList, true, CallLogFilterDialog.ifStartTimeEnabled, CallLogFilterDialog.ifEndTimeEnabled, true, true);
+ convertRecordToExpandableDisplayData(filteredList);
+ refreshUI();
+ }
+ break;
+ case REQUEST_ADD_TO_CONTACT:
+ if (resultCode == RESULT_OK) {
+ refreshData();
+ refreshUI();
+ }
+ break;
+ case REQUEST_MAIN_OPTIONS:
+ if (resultCode == RESULT_OK) {
+ int option = i.getIntExtra(Main.MAIN_OPTOINS_CHOICE, -1);
+ switch (option) {
+ case MainChoiceDialog.OPTION_DELETE_ONE:
+ int l_id = 0;
+ if (groupOrChildClick == 0) {
+ l_id = viewGroupList.get(currentGroupPos).getId();
+ } else if (groupOrChildClick == 1) {
+ l_id = viewList.get(currentGroupPos).get(currentChildPos).getId();
+ }
+ deletePhoneLogById(l_id);
+ refreshData();
+ refreshUI();
+ break;
+ case MainChoiceDialog.OPTION_DELETE_FROM_CONTACT:
+ String l_number = "";
+ if (groupOrChildClick == 0) {
+ l_number = viewGroupList.get(currentGroupPos).getTextLine2();
+ } else if (groupOrChildClick == 1) {
+ l_number = viewList.get(currentGroupPos).get(currentChildPos).getTextLine2();
+ }
+ deletePhoneLogByNumber(l_number);
+ refreshData();
+ refreshUI();
+ break;
+ case MainChoiceDialog.OPTION_ADD_TO_CAL:
+ addLogToCalendar();
+ break;
+ case MainChoiceDialog.OPTION_SCH_CAL:
+ scheduleACalendar();
+ break;
+ case MainChoiceDialog.OPTION_COPY:
+ String l_phoneNumber = "";
+ if (groupOrChildClick == 0) {
+ l_phoneNumber = viewGroupList.get(currentGroupPos).getTextLine2();
+ } else if (groupOrChildClick == 1) {
+ l_phoneNumber = viewList.get(currentGroupPos).get(currentChildPos).getTextLine2();
+ }
+ copyTextToClipboard(l_phoneNumber);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+
+ /**
+ * This part of the code deals with main options actions
+ */
+ private static int groupOrChildClick = 0; //0 for group, 1 for child
+ private static int currentGroupPos = 0;
+ private static int currentChildPos = 0;
+ //delete call logs for a certain call number
+ private int deletePhoneLogByNumber(String _number) {
+ String l_queryString = android.provider.CallLog.Calls.NUMBER + "='" + _number + "'";
+ Log.d(TAG, "deletePhoneLogByNumber: " + _number);
+ int l_num_deleted = mContext.getContentResolver().delete(
+ android.provider.CallLog.Calls.CONTENT_URI, l_queryString, null);
+ if (l_num_deleted > 0) {
+ Log.d(TAG, "deletePhoneLogByNumber: " + l_num_deleted + " entries deleted!");
+ Toast.makeText(mContext, l_num_deleted + " entries deleted!", Toast.LENGTH_SHORT).show();
+ } else {
+ Log.d(TAG, "deletePhoneLogByNumber: " + l_num_deleted + " entries deleted!");
+ Toast.makeText(mContext, "phone log not found!", Toast.LENGTH_SHORT).show();
+ }
+ return l_num_deleted;
+ }
+
+ private void deletePhoneLogById(int _id) {
+ String l_queryString = android.provider.CallLog.Calls._ID + "=" + _id;
+ int l_num_deleted = mContext.getContentResolver().delete(
+ android.provider.CallLog.Calls.CONTENT_URI, l_queryString, null);
+ if (l_num_deleted > 0) {
+ Toast.makeText(mContext, l_num_deleted + " entries deleted!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(mContext, "phone log delete failed!", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private void scheduleACalendar() {
+ String l_phoneNumber = "";
+ if (groupOrChildClick == 0) {
+ l_phoneNumber = viewGroupList.get(currentGroupPos).getTextLine2();
+ } else if (groupOrChildClick == 1) {
+ l_phoneNumber = viewList.get(currentGroupPos).get(currentChildPos).getTextLine2();
+ }
+ String l_name = "";
+ if (groupOrChildClick == 0) {
+ l_name = viewGroupList.get(currentGroupPos).getTextLine1Text1();
+ } else if (groupOrChildClick == 1) {
+ l_name = viewList.get(currentGroupPos).get(currentChildPos).getTextLine1Text1();
+ }
+ Intent intent = new Intent(Intent.ACTION_EDIT);
+ intent.setType("vnd.android.cursor.item/event");
+ intent.putExtra("title", "Event with " + l_name);
+ intent.putExtra("description", l_phoneNumber);
+ intent.putExtra("beginTime", System.currentTimeMillis());
+ intent.putExtra("endTime", System.currentTimeMillis() + 1800*1000);
+ intent.putExtra("allDay", 0);
+ intent.putExtra("hasAlarm", 1);
+ try {
+ startActivity(intent);
+ } catch (Exception e) {
+ Toast.makeText(mContext, "Sorry, no compatible calendar is found!", Toast.LENGTH_LONG).show();
+ }
+ }
+ //add to calendar directly
+ private void addLogToCalendar() {
+ AdvancedPhoneLogRecord l_record = null;
+ if (groupOrChildClick == 0) {
+ l_record = viewGroupList.get(currentGroupPos).getAPL();
+ } else if (groupOrChildClick == 1) {
+ l_record = viewList.get(currentGroupPos).get(currentChildPos).getAPL();
+ }
+ Intent intent = new Intent(Intent.ACTION_EDIT);
+ intent.setType("vnd.android.cursor.item/event");
+ //title according to call type
+ String title = "";
+ switch (l_record.aplr_type) {
+ case android.provider.CallLog.Calls.INCOMING_TYPE:
+ title = "Incoming Call from ";
+ break;
+ case android.provider.CallLog.Calls.OUTGOING_TYPE:
+ title = "Outgoing Call with ";
+ break;
+ case android.provider.CallLog.Calls.MISSED_TYPE:
+ title = "Miss Call from ";
+ break;
+ }
+ intent.putExtra("title", title + l_record.aplr_name);
+ intent.putExtra("description", l_record.aplr_number);
+ intent.putExtra("beginTime", l_record.aplr_time.getTime());
+ intent.putExtra("endTime", l_record.aplr_time.getTime() + l_record.aplr_duration*1000);
+ intent.putExtra("allDay", 0);
+ intent.putExtra("hasAlarm", 0);
+ try {
+ startActivity(intent);
+ } catch (Exception e) {
+ Toast.makeText(mContext, "Sorry, no compatible calendar is found!", Toast.LENGTH_LONG).show();
+ }
+ }
+
+ private void copyTextToClipboard(String _text) {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+ clipboard.setText(_text);
+ Toast.makeText(mContext, _text + " copied to clipboard", Toast.LENGTH_SHORT).show();
+ }
+
+ /**
+ *
+ */
+ private void sendEmailToRequestAFeature() {
+ final Intent l_emailIntent = new Intent(android.content.Intent.ACTION_SEND);
+ l_emailIntent.setType("plain/text");
+ String l_content = "Please describe the feature you want to see in future release " +
+ "as detailed as possible. Your help to improve this app is deeply appreciated!";
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"liuf0005@gmail.com"});
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "APL: Request a Feature");
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, l_content);
+ startActivity(l_emailIntent);
+ }
+
+ private void sendEmailToReportABug() {
+ final Intent l_emailIntent = new Intent(android.content.Intent.ACTION_SEND);
+ l_emailIntent.setType("plain/text");
+ String l_content = "Please describe how this bug occurred as detailed as possible. Your help to improve" +
+ " this app is deeply appreciated!";
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"liuf0005@gmail.com"});
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "APL: Report a Bug");
+ l_emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, l_content);
+ startActivity(l_emailIntent);
+ }
+
+ private void shareTheApp() {
+ final Intent l_shareIntent = new Intent(android.content.Intent.ACTION_SEND);
+ l_shareIntent.setType("text/plain");
+ String l_title = "Advanced Phone Log, take a look";
+ String l_content = "Take a look at the app: Advanced Phone Log. It allows you " +
+ "to view and manage your phone call on Android more conveniently.";
+ l_shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, l_title);
+ l_shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, l_content);
+ Intent.createChooser(l_shareIntent, "Select a way to share");
+ startActivity(l_shareIntent);
+ }
+
+ private void getTS2() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:roman10reborn.topsecret.main"));
+ startActivity(intent);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/dialogs/CallLogFilterDialog.java b/src/roman10reborn/dialogs/CallLogFilterDialog.java
new file mode 100644
index 0000000..f796959
--- /dev/null
+++ b/src/roman10reborn/dialogs/CallLogFilterDialog.java
@@ -0,0 +1,398 @@
+package roman10reborn.dialogs;
+
+import java.util.Calendar;
+
+import roman10reborn.apl.main.R;
+import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.InputType;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.EditText;
+import android.widget.Spinner;
+
+public class CallLogFilterDialog extends Activity {
+ private Spinner spinner_callType;
+ //private TextView text_callType, text_startTime, text_endTime;
+ private EditText edit_startTime, edit_endTime;
+ private Button btn_startTime, btn_endTime;
+ //private TextView text_name;
+ private EditText edit_name;
+ //private TextView text_number;
+ private EditText edit_number;
+
+ private Button btn_ok, btn_cancel, btn_save, btn_reset;
+
+ private Context mContext;
+
+ private static final String[] callTypeStrings = new String[] {
+ "All", "Missed", "Incoming", "Outgoing"
+ };
+ private static int l_filter_callType = 0;
+ public static int FILTER_CALLTYPE_ALL = 0;
+ public static int FILTER_CALLTYPE_MISSED = android.provider.CallLog.Calls.MISSED_TYPE;
+ public static int FILTER_CALLTYPE_IN = android.provider.CallLog.Calls.INCOMING_TYPE;
+ public static int FILTER_CALLTYPE_OUT = android.provider.CallLog.Calls.OUTGOING_TYPE;
+ public static int filter_callType = FILTER_CALLTYPE_ALL;
+
+ public static boolean ifStartTimeEnabled = false;
+ public static int startYear = 0;
+ public static int startMonth = 0;
+ public static int startDay = 0;
+
+ public static boolean ifEndTimeEnabled = false;
+ public static int endYear = 0;
+ public static int endMonth = 0;
+ public static int endDay = 0;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = this.getApplicationContext();
+ //set up GUI
+ this.setContentView(R.layout.calllog_filter_dialog);
+ this.setTitle("Specify a Phone Log Filter");
+ //spinner
+ //text_callType = (TextView) findViewById(R.id.calllog_filter_dialog_text2);
+ spinner_callType = (Spinner) findViewById(R.id.calllog_filter_dialog_spin1);
+ ArrayAdapter adapter = new ArrayAdapter(mContext, android.R.layout.simple_spinner_item, callTypeStrings);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner_callType.setAdapter(adapter);
+ spinner_callType.setSelection(l_filter_callType);
+ spinner_callType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ public void onItemSelected(AdapterView> arg0, View arg1,
+ int arg2, long arg3) {
+ l_filter_callType = (int) arg3;
+ switch (l_filter_callType) {
+ case 0:
+ filter_callType = FILTER_CALLTYPE_ALL;
+ break;
+ case 1:
+ filter_callType = FILTER_CALLTYPE_MISSED;
+ break;
+ case 2:
+ filter_callType = FILTER_CALLTYPE_IN;
+ break;
+ case 3:
+ filter_callType = FILTER_CALLTYPE_OUT;
+ break;
+ }
+ }
+
+ public void onNothingSelected(AdapterView> arg0) {
+ }
+ });
+ //start time
+ //text_startTime = (TextView) findViewById(R.id.calllog_filter_dialog_text2);
+ edit_startTime = (EditText) findViewById(R.id.calllog_filter_dialog_edit2);
+ btn_startTime = (Button) findViewById(R.id.calllog_filter_dialog_btn_start_time);
+ btn_startTime.setText("Enable");
+ edit_startTime.setEnabled(false);
+ btn_startTime.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ if (ifStartTimeEnabled) {
+ showDialog(DATE_DIALOG_ID1);
+ } else {
+ ifStartTimeEnabled = true;
+ initStartTimeFields();
+ }
+ }
+ });
+ //end time
+ //text_endTime = (TextView) findViewById(R.id.calllog_filter_dialog_text3);
+ edit_endTime = (EditText) findViewById(R.id.calllog_filter_dialog_edit3);
+ btn_endTime = (Button) findViewById(R.id.calllog_filter_dialog_btn_end_time);
+ edit_endTime.setEnabled(false);
+ btn_endTime.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ if (ifEndTimeEnabled) {
+ showDialog(DATE_DIALOG_ID2);
+ } else {
+ ifEndTimeEnabled = true;
+ initEndTimeFields();
+ }
+ }
+ });
+ if (ifStartTimeEnabled) {
+ initStartTimeFields();
+ } else {
+ resetStartTimeFields();
+ }
+ if (ifEndTimeEnabled) {
+ initEndTimeFields();
+ } else {
+ resetEndTimeFields();
+ }
+ //name
+ edit_name = (EditText) findViewById(R.id.calllog_filter_dialog_edit4);
+ edit_name.setInputType(InputType.TYPE_CLASS_TEXT);
+ edit_name.setHint("Any, Long Press for Names");
+ setNameEdit();
+ edit_name.setOnLongClickListener(new View.OnLongClickListener() {
+ public boolean onLongClick(View v) {
+ //list out all names in the logs
+ Intent l_intent = new Intent();
+ l_intent.setClass(mContext, roman10reborn.dialogs.FilterNameListDialog.class);
+ startActivityForResult(l_intent, REQUEST_FILTER_NAMES);
+ return true;
+ }
+ });
+ //number
+ edit_number = (EditText) findViewById(R.id.calllog_filter_dialog_edit5);
+ edit_number.setHint("Any, Long Press for Num");
+ setNumberEdit();
+ edit_number.setInputType(InputType.TYPE_CLASS_PHONE);
+ edit_number.setOnLongClickListener(new View.OnLongClickListener() {
+ public boolean onLongClick(View v) {
+ //list out all numbers available
+ Intent l_intent = new Intent();
+ l_intent.setClass(mContext, roman10reborn.dialogs.FilterNumberListDialog.class);
+ startActivityForResult(l_intent, REQUEST_FILTER_NUMBERS);
+ return true;
+ }
+ });
+ //buttons
+ btn_ok = (Button) findViewById(R.id.calllog_filter_dialog_ok);
+ btn_ok.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_OK);
+ finish();
+ }
+ });
+ btn_cancel = (Button) findViewById(R.id.calllog_filter_dialog_cancel);
+ btn_cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+ btn_save = (Button) findViewById(R.id.calllog_filter_dialog_save);
+ btn_save.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //save to short cut, pop up a window to explain the
+ }
+ });
+ btn_reset = (Button) findViewById(R.id.calllog_filter_dialog_reset);
+ btn_reset.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //reset to default settings
+ resetFilter();
+ }
+ });
+
+ int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth()/6*5;
+ btn_ok.setWidth(screenWidth/4);
+ btn_cancel.setWidth(screenWidth/4);
+ btn_save.setWidth(screenWidth/4);
+ btn_reset.setWidth(screenWidth/4);
+ }
+
+ private void resetFilter() {
+ l_filter_callType = 0;
+ filter_callType = FILTER_CALLTYPE_ALL;
+ spinner_callType.setSelection(0);
+ ifStartTimeEnabled = false;
+ resetStartTimeFields();
+ ifEndTimeEnabled = false;
+ resetEndTimeFields();
+ edit_name.setText("");
+ FilterNameListDialog.selectedNamesList.clear();
+ int l_size = FilterNameListDialog.ifSelected.size();
+ for (int i = 0; i < l_size; ++i){
+ FilterNameListDialog.ifSelected.set(i, false);
+ }
+ edit_number.setText("");
+ l_size = FilterNumberListDialog.ifSelected.size();
+ FilterNumberListDialog.selectedNumbersList.clear();
+ for (int i = 0; i < l_size; ++i){
+ FilterNameListDialog.ifSelected.set(i, false);
+ }
+ }
+
+ private void resetStartTimeFields() {
+ edit_startTime.setText("");
+ edit_startTime.setKeyListener(null);
+ btn_startTime.setText("Enable");
+ }
+
+ private void resetEndTimeFields() {
+ edit_endTime.setText("");
+ edit_endTime.setKeyListener(null);
+ btn_endTime.setText("Enable");
+ }
+
+ private void initStartTimeFields() {
+ if ((startYear == 0) && (startMonth == 0) && (startDay == 0)) {
+ final Calendar c = Calendar.getInstance();
+ startYear = c.get(Calendar.YEAR);
+ startMonth = c.get(Calendar.MONTH);
+ startDay = c.get(Calendar.DAY_OF_MONTH);
+ }
+ edit_startTime.setKeyListener(null);
+ edit_startTime.setText( new StringBuilder()
+ .append(startMonth + 1).append("-")
+ .append(startDay).append("-")
+ .append(startYear).append(" ")
+ );
+ btn_startTime.setText("Set");
+ }
+
+ private void initEndTimeFields() {
+ if ((endYear == 0) && (endMonth == 0) && (endDay == 0)) {
+ final Calendar c = Calendar.getInstance();
+ endYear = c.get(Calendar.YEAR);
+ endMonth = c.get(Calendar.MONTH);
+ endDay = c.get(Calendar.DAY_OF_MONTH);
+ }
+ edit_endTime.setKeyListener(null);
+ edit_endTime.setText( new StringBuilder()
+ .append(endMonth + 1).append("-")
+ .append(endDay).append("-")
+ .append(endYear).append(" ")
+ );
+ btn_endTime.setText("Set");
+ }
+
+ private static final int DATE_DIALOG_ID1 = 1;
+ private static final int DATE_DIALOG_ID2 = 2;
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DATE_DIALOG_ID1:
+ return new DatePickerDialog(this,
+ mDateSetListener1,
+ startYear, startMonth, startDay);
+ case DATE_DIALOG_ID2:
+ return new DatePickerDialog(this,
+ mDateSetListener2,
+ endYear, endMonth, endDay);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ switch (id) {
+ case DATE_DIALOG_ID1:
+ ((DatePickerDialog) dialog).updateDate(startYear, startMonth, startDay);
+ break;
+ case DATE_DIALOG_ID2:
+ ((DatePickerDialog) dialog).updateDate(endYear, endMonth, endDay);
+ break;
+ }
+ }
+
+ private DatePickerDialog.OnDateSetListener mDateSetListener1 =
+ new DatePickerDialog.OnDateSetListener() {
+ public void onDateSet(DatePicker view, int year,
+ int monthOfYear, int dayOfMonth) {
+ startYear = year;
+ startMonth = monthOfYear;
+ startDay = dayOfMonth;
+ updateDate1();
+ }
+ };
+ private DatePickerDialog.OnDateSetListener mDateSetListener2 =
+ new DatePickerDialog.OnDateSetListener() {
+
+ public void onDateSet(DatePicker view, int year, int monthOfYear,
+ int dayOfMonth) {
+ endYear = year;
+ endMonth = monthOfYear;
+ endDay = dayOfMonth;
+ updateDate2();
+ }
+ };
+
+ private void updateDate1() {
+ edit_startTime.setText(
+ new StringBuilder()
+ // Month is 0 based so add 1
+ .append(startMonth + 1).append("-")
+ .append(startDay).append("-")
+ .append(startYear).append(" ")
+ );
+ }
+
+ private void updateDate2() {
+ edit_endTime.setText(
+ new StringBuilder()
+ // Month is 0 based so add 1
+ .append(endMonth + 1).append("-")
+ .append(endDay).append("-")
+ .append(endYear).append(" ")
+ );
+ }
+
+ private void setNameEdit() {
+ int l_size = FilterNameListDialog.selectedNamesList.size();
+ String l_text = "";
+ if (l_size == 0) {
+ //do nothing
+ } else if (l_size == 1) {
+ l_text = FilterNameListDialog.selectedNamesList.get(0);
+ }
+ else {
+ int j = 0;
+ int l_cnt = FilterNameListDialog.selectedNamesList.size();
+ for (; j < l_cnt&& j < 3; ++j) {
+ if (j != 0)
+ l_text += ", ";
+ l_text += FilterNameListDialog.selectedNamesList.get(j);
+ }
+ if (j < l_cnt)
+ l_text += " ...";
+ }
+ edit_name.setText(l_text);
+
+ }
+
+ private void setNumberEdit() {
+ int l_size = FilterNumberListDialog.selectedNumbersList.size();
+ String l_text = "";
+ if (l_size == 0) {
+ //do nothing
+ } else if (l_size == 1) {
+ l_text = FilterNumberListDialog.selectedNumbersList.get(0);
+ }
+ else {
+ int j = 0;
+ int l_cnt = FilterNumberListDialog.selectedNumbersList.size();
+ for (; j < l_cnt&& j < 3; ++j) {
+ if (j != 0)
+ l_text += ", ";
+ l_text += FilterNumberListDialog.selectedNumbersList.get(j);
+ }
+ if (j < l_cnt)
+ l_text += " ...";
+ }
+ edit_number.setText(l_text);
+ }
+
+ private static final int REQUEST_FILTER_NAMES = 1;
+ private static final int REQUEST_FILTER_NUMBERS = 2;
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent i) {
+ super.onActivityResult(requestCode, resultCode, i);
+ switch (requestCode) {
+ case REQUEST_FILTER_NAMES:
+ if (resultCode == RESULT_OK) {
+ setNameEdit();
+ }
+ break;
+ case REQUEST_FILTER_NUMBERS:
+ if (resultCode == RESULT_OK) {
+ setNumberEdit();
+ }
+ break;
+ }
+
+ }
+}
diff --git a/src/roman10reborn/dialogs/FilterNameListDialog.java b/src/roman10reborn/dialogs/FilterNameListDialog.java
new file mode 100644
index 0000000..2218ae7
--- /dev/null
+++ b/src/roman10reborn/dialogs/FilterNameListDialog.java
@@ -0,0 +1,119 @@
+package roman10reborn.dialogs;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import roman10reborn.apl.data2.BooleanArrayList;
+import roman10reborn.apl.main.Main;
+import roman10reborn.apl.main.R;
+import roman10reborn.utils.ConstantStatic;
+import roman10reborn.utils.SortingUtilsStatic;
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+
+public class FilterNameListDialog extends ListActivity {
+ private Button btn_ok, btn_cancel, btn_all, btn_none;
+ private ArrayList namesList = new ArrayList();
+
+ public static BooleanArrayList ifSelected = new BooleanArrayList(50);
+ public static ArrayList selectedNamesList = new ArrayList();
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ this.setContentView(R.layout.calllog_filter_name_list_dialog);
+ this.setTitle("Names of Logs Shown");
+ btn_ok = (Button) findViewById(R.id.calllog_filter_name_list_multi_btn_second);
+ btn_ok.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_OK);
+ selectedNamesList.clear();
+ int l_size = ifSelected.size();
+ for (int i = 0; i < l_size; ++i) {
+ if (ifSelected.get(i)) {
+ selectedNamesList.add(namesList.get(i));
+ }
+ }
+ finish();
+ }
+ });
+ btn_cancel = (Button) findViewById(R.id.calllog_filter_name_list_multi_btn_third);
+ btn_cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ selectedNamesList.clear();
+ finish();
+ }
+ });
+ btn_all = (Button) findViewById(R.id.calllog_filter_name_list_multi_btn_first);
+ btn_all.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_size = FilterNameListDialog.this.getListAdapter().getCount();
+ for (int i = 0; i < l_size; ++i) {
+ FilterNameListDialog.this.getListView().setItemChecked(i, true);
+ ifSelected.set(i, true);
+ }
+ }
+ });
+ btn_none = (Button) findViewById(R.id.calllog_filter_name_list_multi_btn_forth);
+ btn_none.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_size = FilterNameListDialog.this.getListAdapter().getCount();
+ for (int i = 0; i < l_size; ++i) {
+ FilterNameListDialog.this.getListView().setItemChecked(i, false);
+ ifSelected.set(i, false);
+ }
+
+ }
+ });
+ int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth()/6*5;
+ btn_ok.setWidth(screenWidth/4);
+ btn_cancel.setWidth(screenWidth/4);
+ btn_all.setWidth(screenWidth/4);
+ btn_none.setWidth(screenWidth/4);
+ //set up the list view
+ namesList = getNameListFromCurrentLogs();
+ setListAdapter(new ArrayAdapter(this,
+ android.R.layout.simple_list_item_multiple_choice, namesList));
+ final ListView listView = getListView();
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ initChecked();
+ }
+
+ private void initChecked() {
+ int l_size = ifSelected.size();
+ for (int i = 0; i< l_size; ++i) {
+ if (ifSelected.get(i)) {
+ FilterNameListDialog.this.getListView().setItemChecked(i, true);
+ }
+ }
+ }
+
+ private ArrayList getNameListFromCurrentLogs() {
+ Set l_set = new HashSet();
+ int l_size = Main.recordList.size();
+ for (int i = 0; i < l_size; ++i) {
+ String name = Main.recordList.get(i).aplr_name;
+ l_set.add((name == null || name.compareTo("") == 0) ? ConstantStatic.UNKNOWN : name);
+ }
+ ArrayList l_names = new ArrayList(l_set);
+ SortingUtilsStatic.sortStringAsc(l_names);
+ //indicates all are not selected
+ for (int i = 0; i < l_names.size(); ++i) {
+ ifSelected.add(false);
+ }
+ return l_names;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+ //selectedNamesList.add(namesList.get(position));
+ ifSelected.set(position, !ifSelected.get(position));
+ }
+}
diff --git a/src/roman10reborn/dialogs/FilterNumberListDialog.java b/src/roman10reborn/dialogs/FilterNumberListDialog.java
new file mode 100644
index 0000000..3aef61e
--- /dev/null
+++ b/src/roman10reborn/dialogs/FilterNumberListDialog.java
@@ -0,0 +1,117 @@
+package roman10reborn.dialogs;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import roman10reborn.apl.data2.BooleanArrayList;
+import roman10reborn.apl.main.Main;
+import roman10reborn.apl.main.R;
+import roman10reborn.utils.ConstantStatic;
+import roman10reborn.utils.SortingUtilsStatic;
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+
+public class FilterNumberListDialog extends ListActivity {
+ private Button btn_ok, btn_cancel, btn_all, btn_none;
+ private ArrayList numbersList = new ArrayList();
+
+ public static BooleanArrayList ifSelected = new BooleanArrayList(50);
+ public static ArrayList selectedNumbersList = new ArrayList();
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ this.setContentView(R.layout.calllog_filter_number_list_dialog);
+ this.setTitle("Numbers of Logs Shown");
+ btn_ok = (Button) findViewById(R.id.calllog_filter_number_list_multi_btn_second);
+ btn_ok.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ selectedNumbersList.clear();
+ int l_size = ifSelected.size();
+ for (int i = 0; i < l_size; ++i) {
+ if (ifSelected.get(i)) {
+ selectedNumbersList.add(numbersList.get(i));
+ }
+ }
+ setResult(RESULT_OK);
+ finish();
+ }
+ });
+ btn_cancel = (Button) findViewById(R.id.calllog_filter_number_list_multi_btn_third);
+ btn_cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ selectedNumbersList.clear();
+ finish();
+ }
+ });
+ btn_all = (Button) findViewById(R.id.calllog_filter_number_list_multi_btn_first);
+ btn_all.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_size = FilterNumberListDialog.this.getListAdapter().getCount();
+ for (int i = 0; i < l_size; ++i) {
+ ifSelected.set(i, true);
+ FilterNumberListDialog.this.getListView().setItemChecked(i, true);
+ }
+ }
+ });
+ btn_none = (Button) findViewById(R.id.calllog_filter_number_list_multi_btn_forth);
+ btn_none.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_size = FilterNumberListDialog.this.getListAdapter().getCount();
+ for (int i = 0; i < l_size; ++i) {
+ ifSelected.set(i, false);
+ FilterNumberListDialog.this.getListView().setItemChecked(i, false);
+ }
+ }
+ });
+ int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth()/6*5;
+ btn_ok.setWidth(screenWidth/4);
+ btn_cancel.setWidth(screenWidth/4);
+ btn_all.setWidth(screenWidth/4);
+ btn_none.setWidth(screenWidth/4);
+ //set up the list view
+ numbersList = getNumberListFromCurrentLogs();
+ setListAdapter(new ArrayAdapter(this,
+ android.R.layout.simple_list_item_multiple_choice, numbersList));
+ final ListView listView = getListView();
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ initChecked();
+ }
+
+ private void initChecked() {
+ int l_size = ifSelected.size();
+ for (int i = 0; i< l_size; ++i) {
+ if (ifSelected.get(i)) {
+ FilterNumberListDialog.this.getListView().setItemChecked(i, true);
+ }
+ }
+ }
+
+ private ArrayList getNumberListFromCurrentLogs() {
+ Set l_set = new HashSet();
+ int l_size = Main.recordList.size();
+ for (int i = 0; i < l_size; ++i) {
+ String number = Main.recordList.get(i).aplr_number;
+ l_set.add(number.compareTo("-1")==0 ? ConstantStatic.NOTAVAIL : number);
+ }
+ ArrayList l_numbers = new ArrayList(l_set);
+ SortingUtilsStatic.sortStringAsc(l_numbers);
+ for (int i = 0; i < l_numbers.size(); ++i) {
+ ifSelected.add(false);
+ }
+ return l_numbers;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+ ifSelected.set(position, !ifSelected.get(position));
+ }
+
+}
diff --git a/src/roman10reborn/dialogs/MainChoiceDialog.java b/src/roman10reborn/dialogs/MainChoiceDialog.java
new file mode 100644
index 0000000..2dcc9d1
--- /dev/null
+++ b/src/roman10reborn/dialogs/MainChoiceDialog.java
@@ -0,0 +1,67 @@
+package roman10reborn.dialogs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import roman10reborn.apl.main.Main;
+import roman10reborn.apl.main.R;
+import roman10reborn.apl.main.R.color;
+import roman10reborn.iconifiedlist.IconifiedText;
+import roman10reborn.iconifiedlist.IconifiedTextListAdapter;
+import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class MainChoiceDialog extends ListActivity {
+ private static final String[] options = new String[] {
+ "Delete this Log", "Delete All Logs of this Number", "Add to Calendar",
+ "Schedule an Event","Copy Number to Clipboard"
+ };
+ public static final int OPTION_DELETE_ONE = 0;
+ public static final int OPTION_DELETE_FROM_CONTACT = 1;
+ public static final int OPTION_ADD_TO_CAL = 2;
+ public static final int OPTION_SCH_CAL = 3;
+ public static final int OPTION_COPY = 4;
+ private List optionsList = new ArrayList();
+ private Context mContext;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.setContentView(R.layout.main_choice_dialog);
+ //this.getListView().setBackgroundColor(color.solid_white);
+ mContext = this.getApplicationContext();
+ //IconifiedTextListAdapter adapter = new IconifiedTextListAdapter(mContext);
+ //convertOptionsToDisplayData();
+ //adapter.setListItems(optionsList);
+ //this.setListAdapter(adapter);
+ setListAdapter(new ArrayAdapter(this,
+ android.R.layout.simple_list_item_single_choice, options));
+
+ final ListView listView = getListView();
+
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+
+ private void convertOptionsToDisplayData() {
+ optionsList.clear();
+ for (int i = 0; i < options.length; ++i) {
+ IconifiedText oneOption = new IconifiedText(options[i]);
+ optionsList.add(oneOption);
+ }
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Intent l_intent = new Intent();
+ l_intent.putExtra(Main.MAIN_OPTOINS_CHOICE, position);
+ setResult(RESULT_OK, l_intent);
+ finish();
+ }
+}
diff --git a/src/roman10reborn/dialogs/SingleChoiceForSorting.java b/src/roman10reborn/dialogs/SingleChoiceForSorting.java
new file mode 100644
index 0000000..0b557f3
--- /dev/null
+++ b/src/roman10reborn/dialogs/SingleChoiceForSorting.java
@@ -0,0 +1,49 @@
+package roman10reborn.dialogs;
+
+import roman10reborn.apl.main.R;
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class SingleChoiceForSorting extends ListActivity {
+ private static final String[] sortingOptionStrings = new String[] {
+ "Sort by Date Des", "Sort by Date Asc", "Sort by Name Des", "Sort by Name Asc",
+ "Sort by Talk Time Des", "Sort by Talk Time Asc"
+ };
+
+ public static final int SORT_DATE_DES = 1;
+ public static final int SORT_DATE_ASC = 2;
+ public static final int SORT_NAME_DES = 3;
+ public static final int SORT_NAME_ASC = 4;
+ public static final int SORT_DURATION_DES = 5;
+ public static final int SORT_DURATION_ASC = 6;
+
+ public static final String SORT_OPTION = "SORT_OPTION";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.setContentView(R.layout.single_choice_for_sorting);
+ this.setTitle("Choose One Option");
+
+ setListAdapter(new ArrayAdapter(this,
+ android.R.layout.simple_list_item_single_choice, sortingOptionStrings));
+
+ final ListView listView = getListView();
+
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id){
+ super.onListItemClick(l, v, position, id);
+ Intent l_intent = new Intent();
+ l_intent.putExtra(SORT_OPTION, position + 1);
+ setResult(RESULT_OK, l_intent);
+ finish();
+ }
+}
diff --git a/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedText.java b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedText.java
new file mode 100644
index 0000000..e587905
--- /dev/null
+++ b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedText.java
@@ -0,0 +1,178 @@
+package roman10reborn.expandableiconifiedlist;
+
+import roman10reborn.apl.data2.AdvancedPhoneLogRecord;
+import android.graphics.drawable.Drawable;
+
+public class ExpandableThreeLinesIconifiedText implements Comparable{
+ private String mTextLine1_text1 = "";
+ private String mTextLine1_text2 = "";
+ private String mTextLine2 = "";
+ private String mTextLine3 = "";
+ private Drawable mLeftIcon = null;
+ private Drawable mRightIcon = null;
+ private String mLeftIconText = "";
+ private String mRightIconText = "";
+ private boolean mSelectable = true;
+ private int mId;
+ private AdvancedPhoneLogRecord mApl; //used to check for phoneLogRecord
+
+ private Drawable mRightIcon1, mRightIcon2;
+ private int state = 0;
+
+ public ExpandableThreeLinesIconifiedText(String _iconLine, String _iconRightLine,
+ String _line1_text1,
+ String _line1_text2,
+ String _line2, String _line3, Drawable _leftIcon,
+ Drawable _rightIcon, int _id, AdvancedPhoneLogRecord _mApl) {
+ mLeftIcon = _leftIcon;
+ mRightIcon = _rightIcon;
+ mLeftIconText = _iconLine;
+ mRightIconText = _iconRightLine;
+ mTextLine1_text1 = _line1_text1;
+ mTextLine1_text2 = _line1_text2;
+ mTextLine2 = _line2;
+ mTextLine3 = _line3;
+ mId = _id;
+ mApl = _mApl;
+ }
+
+ public ExpandableThreeLinesIconifiedText(String _iconLine, String _iconRightLine,
+ String _line1_text1,
+ String _line1_text2,
+ String _line2, String _line3, Drawable _leftIcon,
+ Drawable _rightIcon1, Drawable _rightIcon2, int _id,
+ AdvancedPhoneLogRecord _mApl) {
+ mLeftIcon = _leftIcon;
+ mRightIcon1 = _rightIcon1;
+ mRightIcon2 = _rightIcon2;
+ mLeftIconText = _iconLine;
+ mRightIconText = _iconRightLine;
+ mTextLine1_text1 = _line1_text1;
+ mTextLine1_text2 = _line1_text2;
+ mTextLine2 = _line2;
+ mTextLine3 = _line3;
+ mId = _id;
+ mApl = _mApl;
+ }
+
+ public AdvancedPhoneLogRecord getAPL() {
+ return mApl;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public void setId(int _id) {
+ mId = _id;
+ }
+
+ public boolean isSelectable() {
+ return mSelectable;
+ }
+
+ public void setSelectable(boolean selectable) {
+ mSelectable = selectable;
+ }
+
+ public String getLeftIconText() {
+ return mLeftIconText;
+ }
+
+ public String getRightIconText() {
+ return mRightIconText;
+ }
+
+ public String getTextLine1Text1() {
+ return mTextLine1_text1;
+ }
+
+ public String getTextLine1Text2() {
+ return mTextLine1_text2;
+ }
+
+ public String getTextLine2() {
+ return mTextLine2;
+ }
+
+ public String getTextLine3() {
+ return mTextLine3;
+ }
+
+ public void setLeftIconText(String text) {
+ mLeftIconText = text;
+ }
+
+ public void setRightIconText(String text) {
+ mRightIconText = text;
+ }
+
+ public void setTextLine1Text1(String text) {
+ mTextLine1_text1 = text;
+ }
+
+ public void setTextLine1Text2(String text) {
+ mTextLine1_text2 = text;
+ }
+
+ public void setTextLine2(String text) {
+ mTextLine2 = text;
+ }
+
+ public void setTextLine3(String text) {
+ mTextLine3 = text;
+ }
+
+ public void setLeftIcon(Drawable icon) {
+ mLeftIcon = icon;
+ }
+
+ public Drawable getLeftIcon() {
+ return mLeftIcon;
+ }
+
+ public void setRightIcon(Drawable icon) {
+ mLeftIcon = icon;
+ }
+
+
+ public Drawable getRightIconWithTwoStates() {
+ if (state == 0) {
+ state = 1;
+ return mRightIcon1;
+ } else {
+ state = 0;
+ return mRightIcon2;
+ }
+ }
+
+ public Drawable getRightIcon1() {
+ return mRightIcon1;
+ }
+
+ public Drawable getRightIcon2() {
+ return mRightIcon2;
+ }
+
+ public Drawable getRightIcon() {
+ return mRightIcon;
+ }
+ //compare two objects
+ public int compareTo(ExpandableThreeLinesIconifiedText other) {
+ int l_firstCompare = this.mTextLine1_text1.compareTo(other.mTextLine1_text1);
+ if (l_firstCompare!=0) {
+ return l_firstCompare;
+ } else {
+ int l_secondCompare = this.mTextLine1_text2.compareTo(other.mTextLine1_text2);
+ if (l_secondCompare!=0) {
+ return l_secondCompare;
+ } else {
+ int l_thirdCompare = this.mTextLine2.compareTo(other.mTextLine2);
+ if (l_thirdCompare!=0) {
+ return l_thirdCompare;
+ }
+ return this.mTextLine3.compareTo(other.mTextLine3);
+ }
+ }
+ }
+}
diff --git a/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextChildView.java b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextChildView.java
new file mode 100644
index 0000000..100068f
--- /dev/null
+++ b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextChildView.java
@@ -0,0 +1,151 @@
+package roman10reborn.expandableiconifiedlist;
+
+import roman10reborn.apl.main.R;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.TextView.BufferType;
+
+public class ExpandableThreeLinesIconifiedTextChildView extends RelativeLayout {
+ private TextView mTextLine1_text1, mTextLine1_text2;
+ private TextView mTextLine2;
+ private TextView mTextLine3;
+ //private ImageView mLeftIcon;
+ public ImageButton mLeftIcon;
+ public ImageButton mRightIcon;
+ private TextView mLeftIconText;
+ private TextView mRightIconText;
+ //private ImageView mSeparator;
+ private ExpandableThreeLinesIconifiedText content;
+
+ public ExpandableThreeLinesIconifiedTextChildView(Context context, ExpandableThreeLinesIconifiedText aIconifiedText) {
+ super(context);
+
+ content = aIconifiedText;
+
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.expandable_three_lines_icon_text_child_view, this, true);
+
+ this.setBackgroundColor(Color.DKGRAY);
+
+ //mLeftIcon = (ImageView) findViewById(R.id.expandable_three_lines_icon_text_child_view_left_icon);
+ mLeftIcon = (ImageButton) findViewById(R.id.expandable_three_lines_icon_text_child_view_left_icon);
+ mLeftIcon.setPadding(5, 5, 5, 15); // left, top, right, bottom
+ mLeftIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mLeftIcon.setLayoutParams(new LayoutParams(100, 100));
+ mLeftIcon.setImageDrawable(aIconifiedText.getLeftIcon());
+ //mLeftIcon.setBackgroundResource(R.drawable.photoframe4);
+ mLeftIcon.setClickable(true);
+ mLeftIcon.setFocusable(false);
+
+ mRightIcon = (ImageButton) findViewById(R.id.expandable_three_lines_icon_text_child_view_right_icon);
+ mRightIcon.setPadding(20, 8, 20, 3); // left, top, right, bottom
+ mRightIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mRightIcon.setClickable(true);
+ mRightIcon.setFocusable(false);
+ //note that if the line below is added, the icon will goes to left
+ //mRightIcon.setLayoutParams(new LayoutParams(72, 72));
+ mRightIcon.setMaxHeight(72);
+ mRightIcon.setMinimumHeight(72);
+ mRightIcon.setMaxWidth(72);
+ mRightIcon.setMinimumWidth(72);
+ mRightIcon.setImageDrawable(aIconifiedText.getRightIcon());
+ mRightIcon.setBackgroundResource(R.drawable.list_button);
+ //mRightIcon.setBackgroundColor(Color.WHITE);
+
+ //mSeparator = (ImageView) findViewById(R.id.divider);
+ //mSeparator.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ //mSeparator.setLayoutParams(new LayoutParams(20, 20));
+ //mSeparator.setBackgroundColor(Color.WHITE);
+
+ mLeftIconText = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line_under_left_icon);
+ //mIconText.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mLeftIconText.setText(aIconifiedText.getLeftIconText());
+ mLeftIconText.setVisibility(View.GONE);
+
+ mRightIconText = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line_under_right_icon);
+ mRightIconText.setText(aIconifiedText.getRightIconText());
+
+ mTextLine1_text1 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line1_text1);
+ //mTextLine1.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mTextLine1_text1.setText(aIconifiedText.getTextLine1Text1());
+
+ mTextLine1_text2 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line1_text2);
+ //mTextLine1.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mTextLine1_text2.setText(aIconifiedText.getTextLine1Text2());
+
+ mTextLine2 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line2);
+ //mTextLine2.setTypeface(Typeface.SERIF, 0);
+ mTextLine2.setText(aIconifiedText.getTextLine2());
+
+ mTextLine3 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_child_view_line3);
+ //mTextLine3.setTypeface(Typeface.SERIF, 0);
+ //mTextLine3.setText(aIconifiedText.getTextLine3());
+ SpannableStringBuilder lSpanStr = new SpannableStringBuilder(aIconifiedText.getTextLine3());
+ lSpanStr.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 10, 13, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ mTextLine3.setText(lSpanStr, TextView.BufferType.SPANNABLE);
+ }
+
+ @Override
+ public void setBackgroundColor(int _color) {
+ super.setBackgroundColor(_color);
+ }
+
+ public ExpandableThreeLinesIconifiedText getContent() {
+ return content;
+ }
+
+ public void setTextLine1Text1(String words) {
+ mTextLine1_text1.setText(words);
+ }
+
+ public void setTextLine1Text2(String words) {
+ mTextLine1_text2.setText(words);
+ }
+
+ public void setTextLine2(String words) {
+ mTextLine2.setText(words);
+ }
+
+ public void setTextLine3(String words) {
+ mTextLine3.setText(words);
+ }
+
+ public void setTextLine3(SpannableStringBuilder _panStr, BufferType _type) {
+ mTextLine3.setText(_panStr, _type);
+ }
+
+ public void setLeftIconText(String words) {
+ mLeftIconText.setText(words);
+ }
+
+ public void setRightIconText(String words) {
+ mRightIconText.setText(words);
+ }
+
+ public void setLeftIcon(Drawable bullet) {
+ mLeftIcon.setImageDrawable(bullet);
+ }
+
+ public void setLeftIcon(int res_id) {
+ mLeftIcon.setImageResource(res_id);
+ }
+
+ public void setRightIcon(Drawable bullet) {
+ mRightIcon.setImageDrawable(bullet);
+ }
+
+ public void setRightIcon(int res_id) {
+ mRightIcon.setImageResource(res_id);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextGroupView.java b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextGroupView.java
new file mode 100644
index 0000000..01dd3a6
--- /dev/null
+++ b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextGroupView.java
@@ -0,0 +1,167 @@
+package roman10reborn.expandableiconifiedlist;
+
+import roman10reborn.apl.main.R;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.text.Layout;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.TextView.BufferType;
+
+public class ExpandableThreeLinesIconifiedTextGroupView extends RelativeLayout {
+ private TextView mTextLine1_text1, mTextLine1_text2;
+ private TextView mTextLine2;
+ private TextView mTextLine3;
+ //private ImageView mLeftIcon;
+ public ImageButton mLeftIcon;
+ //private ImageView mRightIcon;
+ public ImageButton mRightIcon;
+ //private TextView mLeftIconText;
+ private TextView mRightIconText;
+ private ExpandableThreeLinesIconifiedText content;
+
+ private View filler, filler2;
+
+ public ExpandableThreeLinesIconifiedTextGroupView(Context context, ExpandableThreeLinesIconifiedText aIconifiedText) {
+ super(context);
+ content = aIconifiedText;
+
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.expandable_three_lines_icon_text_group_view, this, true);
+
+ //mLeftIcon = (ImageView) findViewById(R.id.expandable_three_lines_icon_text_view_left_icon);
+ mLeftIcon = (ImageButton) findViewById(R.id.expandable_three_lines_icon_text_view_left_icon);
+ mLeftIcon.setPadding(5, 5, 5, 15); // left, top, right, bottom
+ mLeftIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mLeftIcon.setLayoutParams(new LayoutParams(100, 100));
+ //mLeftIcon.setBackgroundResource(R.drawable.photoframe4);
+ mLeftIcon.setImageDrawable(aIconifiedText.getLeftIcon());
+ mLeftIcon.setClickable(true);
+ mLeftIcon.setFocusable(false);
+
+// mRightIcon = (ImageView) findViewById(R.id.expandable_three_lines_icon_text_view_right_icon);
+// mRightIcon.setPadding(20, 8, 20, 3); // left, top, right, bottom
+// mRightIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+
+ mRightIcon = (ImageButton) findViewById(R.id.expandable_three_lines_icon_text_view_right_icon);
+ mRightIcon.setPadding(20, 8, 20, 3); // left, top, right, bottom
+ mRightIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mRightIcon.setClickable(true);
+ mRightIcon.setFocusable(false);
+
+ //mRightIcon.setLayoutParams(new LayoutParams(72, 72));
+ mRightIcon.setMaxHeight(72);
+ mRightIcon.setMinimumHeight(72);
+ mRightIcon.setMaxWidth(72);
+ mRightIcon.setMinimumWidth(72);
+ mRightIcon.setImageDrawable(aIconifiedText.getRightIcon1());
+ //mRightIcon.setBackgroundDrawable(null);
+ //mRightIcon.setBackgroundColor(Color.TRANSPARENT);
+ mRightIcon.setBackgroundResource(R.drawable.list_button);
+ //mRightIcon.setAlpha(255);
+ //mRightIcon.setBackgroundDrawable(aIconifiedText.getRightIcon1());
+
+// mLeftIconText = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line_under_left_icon);
+// //mIconText.setTypeface(Typeface.DEFAULT_BOLD, 0);
+// mLeftIconText.setText(aIconifiedText.getLeftIconText());
+// mLeftIconText.setVisibility(View.GONE);
+
+ mRightIconText = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line_under_right_icon);
+ mRightIconText.setText(aIconifiedText.getRightIconText());
+
+ mTextLine1_text1 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line1_text1);
+ //mTextLine1.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mTextLine1_text1.setText(aIconifiedText.getTextLine1Text1());
+
+ mTextLine1_text2 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line1_text2);
+ //mTextLine1.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mTextLine1_text2.setText(aIconifiedText.getTextLine1Text2());
+
+ mTextLine2 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line2);
+ //mTextLine2.setTypeface(Typeface.SERIF, 0);
+ mTextLine2.setText(aIconifiedText.getTextLine2());
+
+ mTextLine3 = (TextView) findViewById(R.id.expandable_three_lines_icon_text_view_line3);
+ //mTextLine3.setTypeface(Typeface.SERIF, 0);
+ //mTextLine3.setText(aIconifiedText.getTextLine3());
+ SpannableStringBuilder lSpanStr = new SpannableStringBuilder(aIconifiedText.getTextLine3());
+ lSpanStr.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 10, 13, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ mTextLine3.setText(lSpanStr, TextView.BufferType.SPANNABLE);
+
+ filler = (View)findViewById(R.id.filler);
+ filler2 = (View)findViewById(R.id.filler2);
+ //filler.setMinimumWidth(5);
+ }
+
+ public void setFillerWidth(int _dip) {
+ //filler.setMinimumWidth(_dip);
+ //filler.setLayoutParams(new LayoutParams(_dip, _dip));
+ //filler.setPadding(_dip-5, 0, 0, 0);
+ //filler.setLayoutParams(new LayoutParams(_dip, RelativeLayout.LayoutParams.FILL_PARENT));
+ if (_dip == 1) {
+ filler.setVisibility(View.INVISIBLE);
+ filler2.setVisibility(View.GONE);
+ } else {
+ filler2.setVisibility(View.INVISIBLE);
+ filler.setVisibility(View.GONE);
+ }
+ }
+
+ public ExpandableThreeLinesIconifiedText getContent() {
+ return content;
+ }
+
+ public void setTextLine1Text1(String words) {
+ mTextLine1_text1.setText(words);
+ }
+
+ public void setTextLine1Text2(String words) {
+ mTextLine1_text2.setText(words);
+ }
+
+ public void setTextLine2(String words) {
+ mTextLine2.setText(words);
+ }
+
+ public void setTextLine3(String words) {
+ mTextLine3.setText(words);
+ }
+
+ public void setTextLine3(SpannableStringBuilder _panStr, BufferType _type) {
+ mTextLine3.setText(_panStr, _type);
+ }
+
+// public void setLeftIconText(String words) {
+// mLeftIconText.setText(words);
+// }
+
+ public void setRightIconText(String words) {
+ mRightIconText.setText(words);
+ }
+
+ public void setLeftIcon(Drawable bullet) {
+ mLeftIcon.setImageDrawable(bullet);
+ }
+
+ public void setLeftIcon(int res_id) {
+ mLeftIcon.setImageResource(res_id);
+ }
+
+ public void setRightIcon(Drawable bullet) {
+ mRightIcon.setImageDrawable(bullet);
+ }
+
+ public void setRightIcon(int res_id) {
+ mRightIcon.setImageResource(res_id);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextListAdapter.java b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextListAdapter.java
new file mode 100644
index 0000000..004bc81
--- /dev/null
+++ b/src/roman10reborn/expandableiconifiedlist/ExpandableThreeLinesIconifiedTextListAdapter.java
@@ -0,0 +1,249 @@
+package roman10reborn.expandableiconifiedlist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import roman10reborn.apl.data2.BooleanArrayList;
+import roman10reborn.apl.main.ContactAccessor;
+import roman10reborn.apl.main.Main;
+import roman10reborn.apl.main.R;
+import roman10reborn.quickactionwindow.ActionItem;
+import roman10reborn.quickactionwindow.QuickAction;
+import roman10reborn.utils.ConstantStatic;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.PopupWindow.OnDismissListener;
+
+public class ExpandableThreeLinesIconifiedTextListAdapter extends BaseExpandableListAdapter {
+ private Context mContext;
+
+ private ArrayList> mItems = new ArrayList>();
+ private ArrayList mGroups = new ArrayList();
+
+ public ExpandableThreeLinesIconifiedTextListAdapter(Context context) {
+ mContext = context;
+ }
+
+ public void setListItems(ArrayList> lit)
+ { mItems = lit; }
+
+ public void setGroups(ArrayList _groups) {
+ mGroups = _groups;
+ }
+
+
+ public Object getChild(int arg0, int arg1) {
+ return mItems.get(arg0).get(arg1);
+ }
+
+ public long getChildId(int arg0, int arg1) {
+ long id = 0;
+ for (int i = 0; i < arg0; ++i) {
+ id += mItems.get(i).size();
+ }
+ return id + arg1;
+ }
+
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
+ ViewGroup parent) {
+ ExpandableThreeLinesIconifiedTextChildView btv;
+ if (convertView == null) {
+ btv = new ExpandableThreeLinesIconifiedTextChildView(mContext, mItems.get(groupPosition).get(childPosition));
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (ExpandableThreeLinesIconifiedTextChildView) convertView;
+ btv.setTextLine1Text1(mItems.get(groupPosition).get(childPosition).getTextLine1Text1());
+ btv.setTextLine1Text2("");
+ btv.setTextLine2(mItems.get(groupPosition).get(childPosition).getTextLine2());
+ btv.setTextLine3(mItems.get(groupPosition).get(childPosition).getTextLine3());
+ btv.setLeftIconText(mItems.get(groupPosition).get(childPosition).getLeftIconText());
+ btv.setRightIconText(mItems.get(groupPosition).get(childPosition).getRightIconText());
+ btv.setLeftIcon(mItems.get(groupPosition).get(childPosition).getLeftIcon());
+ btv.setRightIcon(mItems.get(groupPosition).get(childPosition).getRightIcon());
+ }
+ btv.mRightIcon.setTag(groupPosition + " " + childPosition);
+ btv.mRightIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //call the number
+ String l_pos = (String)v.getTag();
+ int l_emptyPos = l_pos.indexOf(" ");
+ int l_groupPos = Integer.parseInt(l_pos.substring(0, l_emptyPos));
+ int l_childPos = Integer.parseInt(l_pos.substring(l_emptyPos + 1, l_pos.length()));
+ makeACall(mItems.get(l_groupPos).get(l_childPos).getTextLine2());
+ }
+ });
+ btv.mLeftIcon.setTag(groupPosition + " " + childPosition);
+ btv.mLeftIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ String l_pos = (String)v.getTag();
+ int l_emptyPos = l_pos.indexOf(" ");
+ int l_groupPos = Integer.parseInt(l_pos.substring(0, l_emptyPos));
+ int l_childPos = Integer.parseInt(l_pos.substring(l_emptyPos + 1, l_pos.length()));
+ Main.currentPhoneNumber = mItems.get(l_groupPos).get(l_childPos).getTextLine2();
+ Main.currentName = mGroups.get(l_groupPos).getTextLine1Text1();
+ if ((Main.currentPhoneNumber!=null) && (Main.currentPhoneNumber.compareTo("-1")!=0) && (!Main.currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+ popupQuickAction(v);
+ }
+ }
+ });
+ return btv;
+ }
+
+ public int getChildrenCount(int groupPosition) {
+ return mItems.get(groupPosition).size();
+ }
+
+ public Object getGroup(int groupPosition) {
+ return mItems.get(groupPosition);
+ }
+
+ public int getGroupCount() {
+ return mItems.size();
+ }
+
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ public View getGroupView(int groupPosition, boolean isExpanded,
+ View convertView, ViewGroup parent) {
+ ExpandableThreeLinesIconifiedTextGroupView btv;
+ if (convertView == null) {
+ btv = new ExpandableThreeLinesIconifiedTextGroupView(mContext, mGroups.get(groupPosition));
+ if(getChildrenCount(groupPosition)==0) {
+ btv.setFillerWidth(1);
+ } else {
+ btv.setFillerWidth(2);
+ }
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (ExpandableThreeLinesIconifiedTextGroupView) convertView;
+ btv.setTextLine1Text1(mGroups.get(groupPosition).getTextLine1Text1());
+ btv.setTextLine1Text2(mGroups.get(groupPosition).getTextLine1Text2());
+ btv.setTextLine2(mGroups.get(groupPosition).getTextLine2());
+ btv.setTextLine3(mGroups.get(groupPosition).getTextLine3());
+ //btv.setLeftIconText(mGroups.get(groupPosition).getLeftIconText());
+ btv.setRightIconText(mGroups.get(groupPosition).getRightIconText());
+ btv.setLeftIcon(mGroups.get(groupPosition).getLeftIcon());
+ if (isExpanded) {
+ btv.setRightIcon(mGroups.get(groupPosition).getRightIcon2());
+ } else {
+ btv.setRightIcon(mGroups.get(groupPosition).getRightIcon1());
+ }
+ if(getChildrenCount(groupPosition)==0) {
+ btv.setFillerWidth(1);
+ } else {
+ btv.setFillerWidth(2);
+ }
+ }
+ btv.mRightIcon.setTag(groupPosition);
+ btv.mRightIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //call the number
+ int l_groupPos = (Integer)v.getTag();
+ makeACall(mGroups.get(l_groupPos).getTextLine2());
+ }
+ });
+ btv.mLeftIcon.setTag(groupPosition);
+ btv.mLeftIcon.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ int l_groupPos = (Integer)v.getTag();
+ Main.currentPhoneNumber = mGroups.get(l_groupPos).getTextLine2();
+ Main.currentName = mGroups.get(l_groupPos).getTextLine1Text1();
+ if ((Main.currentPhoneNumber!=null) && (Main.currentPhoneNumber.compareTo("-1")!=0) && (!Main.currentPhoneNumber.contains(ConstantStatic.NOTAVAIL))) {
+ popupQuickAction(v);
+ }
+ }
+ });
+ return btv;
+ }
+
+ private void popupQuickAction(View v) {
+ final QuickAction mQuickAction = new QuickAction(v);
+ final ActionItem phoneAction = new ActionItem();
+ phoneAction.setTitle("Call");
+ phoneAction.setIcon(mContext.getResources().getDrawable(R.drawable.phonecall1));
+ final ActionItem smsAction = new ActionItem();
+ smsAction.setTitle("SMS");
+ smsAction.setIcon(mContext.getResources().getDrawable(R.drawable.sms1));
+ final ActionItem contactAction = new ActionItem();
+ if (!Main.currentName.contains(ConstantStatic.UNKNOWN)) {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.viewcontact2));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //view contact
+ viewContact(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ } else {
+ contactAction.setTitle("Contact");
+ contactAction.setIcon(mContext.getResources().getDrawable(R.drawable.addcontact));
+ contactAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ //add phone number to contact
+ Main.addToContact(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ }
+
+ phoneAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Main.makeAPhoneCall(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ smsAction.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Main.sendOutSms(Main.currentPhoneNumber);
+ mQuickAction.dismiss();
+ }
+ });
+ mQuickAction.addActionItem(phoneAction);
+ mQuickAction.addActionItem(smsAction);
+ if (Integer.parseInt(Build.VERSION.SDK) >= Build.VERSION_CODES.ECLAIR) {
+ mQuickAction.addActionItem(contactAction);
+ }
+ //mQuickAction.addActionItem(deleteAction);
+ mQuickAction.setAnimStyle(QuickAction.ANIM_GROW_FROM_RIGHT);
+ mQuickAction.setOnDismissListener(new OnDismissListener(){
+ public void onDismiss() {
+ //do nothing
+ }
+ });
+ mQuickAction.show();
+ }
+
+ //sdk dependent
+ private void viewContact(String _number) {
+ ContactAccessor.getInstance().viewContact(mContext, _number);
+ }
+
+ private void makeACall(String _number) {
+ try {
+ Intent callIntent = new Intent(Intent.ACTION_CALL);
+ callIntent.setData(Uri.parse("tel:" + _number));
+ mContext.startActivity(callIntent);
+ } catch (ActivityNotFoundException e) {
+ //
+ }
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return mItems.get(groupPosition).get(childPosition).isSelectable();
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/iconifiedlist/IconifiedText.java b/src/roman10reborn/iconifiedlist/IconifiedText.java
new file mode 100644
index 0000000..d0290ac
--- /dev/null
+++ b/src/roman10reborn/iconifiedlist/IconifiedText.java
@@ -0,0 +1,67 @@
+package roman10reborn.iconifiedlist;
+
+import android.graphics.drawable.Drawable;
+
+public class IconifiedText implements Comparable{
+ private String mText = "";
+ private String mInfo = "";
+ private Drawable mIcon;
+ private boolean mChecked;
+
+ public IconifiedText(String text, Drawable bullet, boolean _checked, String _hiddenInfo) {
+ mIcon = bullet;
+ mText = text;
+ mChecked = _checked;
+ mInfo = _hiddenInfo;
+ }
+
+ public IconifiedText(String text) {
+ mText = text;
+ mIcon = null;
+ mChecked = false;
+ mInfo = "";
+ }
+
+ public String getInfo() {
+ return mInfo;
+ }
+
+ public void setInfo(String _info) {
+ mInfo = _info;
+ }
+
+ public String getText() {
+ return mText;
+ }
+
+ public void setText(String text) {
+ mText = text;
+ }
+
+ public boolean isSelectable() {
+ return true;
+ }
+
+ public void setIcon(Drawable icon) {
+ mIcon = icon;
+ }
+
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ public void setChecked(boolean _checked) {
+ mChecked = _checked;
+ }
+
+ public boolean getChecked() {
+ return mChecked;
+ }
+
+ public int compareTo(IconifiedText other) {
+ if(this.mText != null)
+ return this.mText.compareTo(other.getText());
+ else
+ throw new IllegalArgumentException();
+ }
+}
diff --git a/src/roman10reborn/iconifiedlist/IconifiedTextListAdapter.java b/src/roman10reborn/iconifiedlist/IconifiedTextListAdapter.java
new file mode 100644
index 0000000..8b2a42c
--- /dev/null
+++ b/src/roman10reborn/iconifiedlist/IconifiedTextListAdapter.java
@@ -0,0 +1,55 @@
+package roman10reborn.iconifiedlist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+public class IconifiedTextListAdapter extends BaseAdapter {
+ private Context mContext;
+
+ private List mItems = new ArrayList();
+
+
+ public IconifiedTextListAdapter(Context context) {
+ mContext = context;
+ }
+
+ public void setListItems(List lit)
+ { mItems = lit; }
+
+ public int getCount() { return mItems.size(); }
+
+ public Object getItem(int position)
+ { return mItems.get(position); }
+
+ public boolean areAllItemsSelectable() { return false; }
+
+ public boolean isSelectable(int position) {
+ return mItems.get(position).isSelectable();
+ }
+
+ /** Use the array index as a unique id. */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /** @param convertView The old view to overwrite, if one is passed
+ * @returns a IconifiedTextView that holds wraps around an IconifiedText */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ IconifiedTextView btv;
+ if (convertView == null) {
+ btv = new IconifiedTextView(mContext, mItems.get(position));
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (IconifiedTextView) convertView;
+ btv.setText(mItems.get(position).getText());
+ btv.setIcon(mItems.get(position).getIcon());
+ btv.setSelected(mItems.get(position).getChecked());
+ }
+ return btv;
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/iconifiedlist/IconifiedTextView.java b/src/roman10reborn/iconifiedlist/IconifiedTextView.java
new file mode 100644
index 0000000..6ce1ae7
--- /dev/null
+++ b/src/roman10reborn/iconifiedlist/IconifiedTextView.java
@@ -0,0 +1,58 @@
+package roman10reborn.iconifiedlist;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class IconifiedTextView extends LinearLayout {
+ private TextView mText;
+ private ImageView mIcon;
+ public static int mCheckbox_id = 1000;
+ public IconifiedTextView(Context context, IconifiedText iconifiedText) {
+ super(context);
+
+ /* First Icon and the Text to the right (horizontal),
+ * not above and below (vertical) */
+ this.setOrientation(HORIZONTAL);
+
+ mIcon = new ImageView(context);
+ mIcon.setPadding(5, 10, 20, 10); // 5px to the right
+ mIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mIcon.setLayoutParams(new LayoutParams(80, 80));
+ //mIcon.setMaxHeight(72);
+ //mIcon.setMaxWidth(72);
+ mIcon.setImageDrawable(iconifiedText.getIcon());
+ mIcon.setVisibility(View.GONE);
+ addView(mIcon);
+
+ mText = new TextView(context);
+ mText.setTypeface(Typeface.SERIF, 0);
+ mText.setTextColor(Color.BLACK);
+ mText.setTextSize(24);
+ mText.setText(iconifiedText.getText());
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
+ params.weight = 1;
+ params.gravity = Gravity.CENTER_VERTICAL;
+ addView(mText, params);
+ }
+
+ public void setText(String words) {
+ mText.setText(words);
+ }
+
+ public void setIcon(Drawable bullet) {
+ mIcon.setImageDrawable(bullet);
+ }
+
+ public void setIcon(int res_id) {
+ mIcon.setImageResource(res_id);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/quickactionwindow/ActionItem.java b/src/roman10reborn/quickactionwindow/ActionItem.java
new file mode 100644
index 0000000..798eb0b
--- /dev/null
+++ b/src/roman10reborn/quickactionwindow/ActionItem.java
@@ -0,0 +1,131 @@
+/**
+ * Lorensius W. L. T
+ *
+ * http://www.londatiga.net
+ *
+ * lorenz@londatiga.net
+ */
+
+package roman10reborn.quickactionwindow;
+
+import android.graphics.drawable.Drawable;
+import android.graphics.Bitmap;
+
+import android.view.View.OnClickListener;
+
+/**
+ * Action item, displayed as menu with icon and text.
+ *
+ * @author Lorensius. W. L. T
+ *
+ */
+public class ActionItem {
+ private Drawable icon;
+ private Bitmap thumb;
+ private String title;
+ private boolean selected;
+ private OnClickListener listener;
+
+ /**
+ * Constructor
+ */
+ public ActionItem() {}
+
+ /**
+ * Constructor
+ *
+ * @param icon {@link Drawable} action icon
+ */
+ public ActionItem(Drawable icon) {
+ this.icon = icon;
+ }
+
+ /**
+ * Set action title
+ *
+ * @param title action title
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Get action title
+ *
+ * @return action title
+ */
+ public String getTitle() {
+ return this.title;
+ }
+
+ /**
+ * Set action icon
+ *
+ * @param icon {@link Drawable} action icon
+ */
+ public void setIcon(Drawable icon) {
+ this.icon = icon;
+ }
+
+ /**
+ * Get action icon
+ * @return {@link Drawable} action icon
+ */
+ public Drawable getIcon() {
+ return this.icon;
+ }
+
+ /**
+ * Set on click listener
+ *
+ * @param listener on click listener {@link View.OnClickListener}
+ */
+ public void setOnClickListener(OnClickListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * Get on click listener
+ *
+ * @return on click listener {@link View.OnClickListener}
+ */
+ public OnClickListener getListener() {
+ return this.listener;
+ }
+
+ /**
+ * Set selected flag;
+ *
+ * @param selected Flag to indicate the item is selected
+ */
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ /**
+ * Check if item is selected
+ *
+ * @return true or false
+ */
+ public boolean isSelected() {
+ return this.selected;
+ }
+
+ /**
+ * Set thumb
+ *
+ * @param thumb Thumb image
+ */
+ public void setThumb(Bitmap thumb) {
+ this.thumb = thumb;
+ }
+
+ /**
+ * Get thumb image
+ *
+ * @return Thumb image
+ */
+ public Bitmap getThumb() {
+ return this.thumb;
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/quickactionwindow/CustomPopupWindow.java b/src/roman10reborn/quickactionwindow/CustomPopupWindow.java
new file mode 100644
index 0000000..bc7ac80
--- /dev/null
+++ b/src/roman10reborn/quickactionwindow/CustomPopupWindow.java
@@ -0,0 +1,221 @@
+/**
+ * Lorensius W. L. T
+ *
+ * http://www.londatiga.net
+ *
+ * lorenz@londatiga.net
+ */
+
+
+package roman10reborn.quickactionwindow;
+
+import roman10reborn.apl.main.R;
+import android.content.Context;
+
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+
+import android.widget.PopupWindow;
+
+/**
+ * This class does most of the work of wrapping the {@link PopupWindow} so it's simpler to use.
+ * Edited by Lorensius. W. L. T
+ *
+ * @author qberticus
+ *
+ */
+public class CustomPopupWindow {
+ protected final View anchor;
+ protected final PopupWindow window;
+ private View root;
+ private Drawable background = null;
+ protected final WindowManager windowManager;
+
+ /**
+ * Create a QuickAction
+ *
+ * @param anchor
+ * the view that the QuickAction will be displaying 'from'
+ */
+ public CustomPopupWindow(View anchor) {
+ this.anchor = anchor;
+ this.window = new PopupWindow(anchor.getContext());
+
+ // when a touch even happens outside of the window
+ // make the window go away
+ window.setTouchInterceptor(new OnTouchListener() {
+ //@Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ CustomPopupWindow.this.window.dismiss();
+
+ return true;
+ }
+ return false;
+ }
+ });
+
+ windowManager = (WindowManager) anchor.getContext().getSystemService(Context.WINDOW_SERVICE);
+
+ onCreate();
+ }
+
+ /**
+ * Anything you want to have happen when created. Probably should create a view and setup the event listeners on
+ * child views.
+ */
+ protected void onCreate() {}
+
+ /**
+ * In case there is stuff to do right before displaying.
+ */
+ protected void onShow() {}
+
+ protected void preShow() {
+ if (root == null) {
+ throw new IllegalStateException("setContentView was not called with a view to display.");
+ }
+
+ onShow();
+
+ if (background == null) {
+ window.setBackgroundDrawable(new BitmapDrawable());
+ } else {
+ window.setBackgroundDrawable(background);
+ }
+
+ // if using PopupWindow#setBackgroundDrawable this is the only values of the width and hight that make it work
+ // otherwise you need to set the background of the root viewgroup
+ // and set the popupwindow background to an empty BitmapDrawable
+
+ window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
+ window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
+ window.setTouchable(true);
+ window.setFocusable(true);
+ window.setOutsideTouchable(true);
+
+ window.setContentView(root);
+ }
+
+ public void setBackgroundDrawable(Drawable background) {
+ this.background = background;
+ }
+
+ /**
+ * Sets the content view. Probably should be called from {@link onCreate}
+ *
+ * @param root
+ * the view the popup will display
+ */
+ public void setContentView(View root) {
+ this.root = root;
+
+ window.setContentView(root);
+ }
+
+ /**
+ * Will inflate and set the view from a resource id
+ *
+ * @param layoutResID
+ */
+ public void setContentView(int layoutResID) {
+ LayoutInflater inflator =
+ (LayoutInflater) anchor.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ setContentView(inflator.inflate(layoutResID, null));
+ }
+
+ /**
+ * If you want to do anything when {@link dismiss} is called
+ *
+ * @param listener
+ */
+ public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
+ window.setOnDismissListener(listener);
+ }
+
+ /**
+ * Displays like a popdown menu from the anchor view
+ */
+ public void showDropDown() {
+ showDropDown(0, 0);
+ }
+
+ /**
+ * Displays like a popdown menu from the anchor view.
+ *
+ * @param xOffset
+ * offset in X direction
+ * @param yOffset
+ * offset in Y direction
+ */
+ public void showDropDown(int xOffset, int yOffset) {
+ preShow();
+
+ window.setAnimationStyle(R.style.Animations_PopDownMenu_Left);
+
+ window.showAsDropDown(anchor, xOffset, yOffset);
+ }
+
+ /**
+ * Displays like a QuickAction from the anchor view.
+ */
+ public void showLikeQuickAction() {
+ showLikeQuickAction(0, 0);
+ }
+
+ /**
+ * Displays like a QuickAction from the anchor view.
+ *
+ * @param xOffset
+ * offset in the X direction
+ * @param yOffset
+ * offset in the Y direction
+ */
+ public void showLikeQuickAction(int xOffset, int yOffset) {
+ preShow();
+
+ window.setAnimationStyle(R.style.Animations_PopUpMenu_Center);
+
+ int[] location = new int[2];
+ anchor.getLocationOnScreen(location);
+
+ Rect anchorRect =
+ new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
+ + anchor.getHeight());
+
+ root.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+ int rootWidth = root.getMeasuredWidth();
+ int rootHeight = root.getMeasuredHeight();
+
+ int screenWidth = windowManager.getDefaultDisplay().getWidth();
+ //int screenHeight = windowManager.getDefaultDisplay().getHeight();
+
+ int xPos = ((screenWidth - rootWidth) / 2) + xOffset;
+ int yPos = anchorRect.top - rootHeight + yOffset;
+
+ // display on bottom
+ if (rootHeight > anchor.getTop()) {
+ yPos = anchorRect.bottom + yOffset;
+
+ window.setAnimationStyle(R.style.Animations_PopDownMenu_Center);
+ }
+
+ window.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
+ }
+
+ public void dismiss() {
+ window.dismiss();
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/quickactionwindow/QuickAction.java b/src/roman10reborn/quickactionwindow/QuickAction.java
new file mode 100644
index 0000000..96214bf
--- /dev/null
+++ b/src/roman10reborn/quickactionwindow/QuickAction.java
@@ -0,0 +1,269 @@
+package roman10reborn.quickactionwindow;
+
+import android.content.Context;
+
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.LinearLayout;
+
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+
+import roman10reborn.apl.main.R;
+
+/**
+
+ */
+public class QuickAction extends CustomPopupWindow {
+ private final View root;
+ private final ImageView mArrowUp;
+ private final ImageView mArrowDown;
+ private final Animation mTrackAnim;
+ private final LayoutInflater inflater;
+ private final Context context;
+
+ public static final int ANIM_GROW_FROM_LEFT = 1;
+ public static final int ANIM_GROW_FROM_RIGHT = 2;
+ public static final int ANIM_GROW_FROM_CENTER = 3;
+ public static final int ANIM_AUTO = 4;
+
+ private int animStyle;
+ private boolean animateTrack;
+ private ViewGroup mTrack;
+ private ArrayList actionList;
+
+ /**
+ * Constructor
+ *
+ * @param anchor {@link View} on where the popup should be displayed
+ */
+ public QuickAction(View anchor) {
+ super(anchor);
+
+ actionList = new ArrayList();
+ context = anchor.getContext();
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ root = (ViewGroup) inflater.inflate(R.layout.quickaction, null);
+
+ mArrowDown = (ImageView) root.findViewById(R.id.arrow_down);
+ mArrowUp = (ImageView) root.findViewById(R.id.arrow_up);
+
+ setContentView(root);
+
+ mTrackAnim = AnimationUtils.loadAnimation(anchor.getContext(), R.anim.rail);
+
+ mTrackAnim.setInterpolator(new Interpolator() {
+ public float getInterpolation(float t) {
+ // Pushes past the target area, then snaps back into place.
+ // Equation for graphing: 1.2-((x*1.6)-1.1)^2
+ final float inner = (t * 1.55f) - 1.1f;
+
+ return 1.2f - inner * inner;
+ }
+ });
+
+ mTrack = (ViewGroup) root.findViewById(R.id.tracks);
+ animStyle = ANIM_AUTO;
+ animateTrack = true;
+ }
+
+ /**
+ * Animate track
+ *
+ * @param animateTrack flag to animate track
+ */
+ public void animateTrack(boolean animateTrack) {
+ this.animateTrack = animateTrack;
+ }
+
+ /**
+ * Set animation style
+ *
+ * @param animStyle animation style, default is set to ANIM_AUTO
+ */
+ public void setAnimStyle(int animStyle) {
+ this.animStyle = animStyle;
+ }
+
+ /**
+ * Add action item
+ *
+ * @param action {@link ActionItem}
+ */
+ public void addActionItem(ActionItem action) {
+ actionList.add(action);
+ }
+
+ /**
+ * Show popup window
+ */
+ public void show () {
+ preShow();
+
+ int[] location = new int[2];
+
+ anchor.getLocationOnScreen(location);
+
+ Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
+ + anchor.getHeight());
+
+ root.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+ int rootWidth = root.getMeasuredWidth();
+ int rootHeight = root.getMeasuredHeight();
+
+ int screenWidth = windowManager.getDefaultDisplay().getWidth();
+ //int screenHeight = windowManager.getDefaultDisplay().getHeight();
+
+ int xPos = (screenWidth - rootWidth) / 2;
+ int yPos = anchorRect.top - rootHeight;
+
+ boolean onTop = true;
+
+ // display on bottom
+ if (rootHeight > anchor.getTop()) {
+ yPos = anchorRect.bottom;
+ onTop = false;
+ }
+
+ showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), anchorRect.centerX());
+
+ setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
+
+ createActionList();
+
+ window.showAtLocation(this.anchor, Gravity.NO_GRAVITY, xPos, yPos);
+
+ if (animateTrack) mTrack.startAnimation(mTrackAnim);
+ }
+
+ /**
+ * Set animation style
+ *
+ * @param screenWidth Screen width
+ * @param requestedX distance from left screen
+ * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor and vice versa
+ */
+ private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
+ int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
+
+ switch (animStyle) {
+ case ANIM_GROW_FROM_LEFT:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
+ break;
+
+ case ANIM_GROW_FROM_RIGHT:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
+ break;
+
+ case ANIM_GROW_FROM_CENTER:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
+ break;
+
+ case ANIM_AUTO:
+ if (arrowPos <= screenWidth/4) {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
+ } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
+ } else {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopDownMenu_Right : R.style.Animations_PopDownMenu_Right);
+ }
+
+ break;
+ }
+ }
+
+ /**
+ * Create action list
+ *
+ */
+ private void createActionList() {
+ View view;
+ String title;
+ Drawable icon;
+ OnClickListener listener;
+ int index = 1;
+
+ for (int i = 0; i < actionList.size(); i++) {
+ title = actionList.get(i).getTitle();
+ icon = actionList.get(i).getIcon();
+ listener = actionList.get(i).getListener();
+
+ view = getActionItem(title, icon, listener);
+
+ view.setFocusable(true);
+ view.setClickable(true);
+
+ mTrack.addView(view, index);
+
+ index++;
+ }
+ }
+
+ /**
+ * Get action item {@link View}
+ *
+ * @param title action item title
+ * @param icon {@link Drawable} action item icon
+ * @param listener {@link View.OnClickListener} action item listener
+ * @return action item {@link View}
+ */
+ private View getActionItem(String title, Drawable icon, OnClickListener listener) {
+ LinearLayout container = (LinearLayout) inflater.inflate(R.layout.action_item, null);
+ ImageView img = (ImageView) container.findViewById(R.id.icon);
+ TextView text = (TextView) container.findViewById(R.id.title);
+
+ if (icon != null) {
+ img.setImageDrawable(icon);
+ } else {
+ img.setVisibility(View.GONE);
+ }
+
+ if (title != null) {
+ text.setText(title);
+ } else {
+ text.setVisibility(View.GONE);
+ }
+
+ if (listener != null) {
+ container.setOnClickListener(listener);
+ }
+
+ return container;
+ }
+
+ /**
+ * Show arrow
+ *
+ * @param whichArrow arrow type resource id
+ * @param requestedX distance from left screen
+ */
+ private void showArrow(int whichArrow, int requestedX) {
+ final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
+ final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
+
+ final int arrowWidth = mArrowUp.getMeasuredWidth();
+
+ showArrow.setVisibility(View.VISIBLE);
+
+ ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
+
+ param.leftMargin = requestedX - arrowWidth / 2;
+
+ hideArrow.setVisibility(View.INVISIBLE);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/quickactionwindow/QuickAction2.java b/src/roman10reborn/quickactionwindow/QuickAction2.java
new file mode 100644
index 0000000..704b450
--- /dev/null
+++ b/src/roman10reborn/quickactionwindow/QuickAction2.java
@@ -0,0 +1,269 @@
+package roman10reborn.quickactionwindow;
+
+import android.content.Context;
+
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+
+import roman10reborn.apl.main.R;
+
+/**
+ * Popup window, shows action list as icon and text like the one in Gallery3D app.
+ *
+ * @author Lorensius. W. T
+ */
+public class QuickAction2 extends CustomPopupWindow {
+ private final View root;
+ private final ImageView mArrowUp;
+ private final ImageView mArrowDown;
+ private final LayoutInflater inflater;
+ private final Context context;
+
+ protected static final int ANIM_GROW_FROM_LEFT = 1;
+ protected static final int ANIM_GROW_FROM_RIGHT = 2;
+ protected static final int ANIM_GROW_FROM_CENTER = 3;
+ protected static final int ANIM_REFLECT = 4;
+ protected static final int ANIM_AUTO = 5;
+
+ private int animStyle;
+ private ViewGroup mTrack;
+ private ScrollView scroller;
+ private ArrayList actionList;
+
+ /**
+ * Constructor
+ *
+ * @param anchor {@link View} on where the popup window should be displayed
+ */
+ public QuickAction2(View anchor) {
+ super(anchor);
+
+ actionList = new ArrayList();
+ context = anchor.getContext();
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ root = (ViewGroup) inflater.inflate(R.layout.popup, null);
+
+ mArrowDown = (ImageView) root.findViewById(R.id.arrow_down);
+ mArrowUp = (ImageView) root.findViewById(R.id.arrow_up);
+
+ setContentView(root);
+
+ mTrack = (ViewGroup) root.findViewById(R.id.tracks);
+ scroller = (ScrollView) root.findViewById(R.id.scroller);
+ animStyle = ANIM_AUTO;
+ }
+
+ /**
+ * Set animation style
+ *
+ * @param animStyle animation style, default is set to ANIM_AUTO
+ */
+ public void setAnimStyle(int animStyle) {
+ this.animStyle = animStyle;
+ }
+
+ /**
+ * Add action item
+ *
+ * @param action {@link ActionItem} object
+ */
+ public void addActionItem(ActionItem action) {
+ actionList.add(action);
+ }
+
+ /**
+ * Show popup window. Popup is automatically positioned, on top or bottom of anchor view.
+ *
+ */
+ public void show () {
+ preShow();
+
+ int xPos, yPos;
+
+ int[] location = new int[2];
+
+ anchor.getLocationOnScreen(location);
+
+ Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
+ + anchor.getHeight());
+
+ createActionList();
+
+ root.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+ int rootHeight = root.getMeasuredHeight();
+ int rootWidth = root.getMeasuredWidth();
+
+ int screenWidth = windowManager.getDefaultDisplay().getWidth();
+ int screenHeight = windowManager.getDefaultDisplay().getHeight();
+
+ //automatically get X coord of popup (top left)
+ if ((anchorRect.left + rootWidth) > screenWidth) {
+ xPos = anchorRect.left - (rootWidth-anchor.getWidth());
+ } else {
+ if (anchor.getWidth() > rootWidth) {
+ xPos = anchorRect.centerX() - (rootWidth/2);
+ } else {
+ xPos = anchorRect.left;
+ }
+ }
+
+ int dyTop = anchorRect.top;
+ int dyBottom = screenHeight - anchorRect.bottom;
+
+ boolean onTop = (dyTop > dyBottom) ? true : false;
+
+ if (onTop) {
+ if (rootHeight > dyTop) {
+ yPos = 15;
+ LayoutParams l = scroller.getLayoutParams();
+ l.height = dyTop - anchor.getHeight();
+ } else {
+ yPos = anchorRect.top - rootHeight;
+ }
+ } else {
+ yPos = anchorRect.bottom;
+
+ if (rootHeight > dyBottom) {
+ LayoutParams l = scroller.getLayoutParams();
+ l.height = dyBottom;
+ }
+ }
+
+ showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), anchorRect.centerX()-xPos);
+
+ setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
+
+ window.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
+ }
+
+ /**
+ * Set animation style
+ *
+ * @param screenWidth screen width
+ * @param requestedX distance from left edge
+ * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view
+ * and vice versa
+ */
+ private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
+ int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
+
+ switch (animStyle) {
+ case ANIM_GROW_FROM_LEFT:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
+ break;
+
+ case ANIM_GROW_FROM_RIGHT:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
+ break;
+
+ case ANIM_GROW_FROM_CENTER:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
+ break;
+
+ case ANIM_REFLECT:
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);
+ break;
+
+ case ANIM_AUTO:
+ if (arrowPos <= screenWidth/4) {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
+ } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
+ } else {
+ window.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
+ }
+
+ break;
+ }
+ }
+
+ /**
+ * Create action list
+ */
+ private void createActionList() {
+ View view;
+ String title;
+ Drawable icon;
+ OnClickListener listener;
+
+ for (int i = 0; i < actionList.size(); i++) {
+ title = actionList.get(i).getTitle();
+ icon = actionList.get(i).getIcon();
+ listener = actionList.get(i).getListener();
+
+ view = getActionItem(title, icon, listener);
+
+ view.setFocusable(true);
+ view.setClickable(true);
+
+ mTrack.addView(view);
+ }
+ }
+
+ /**
+ * Get action item {@link View}
+ *
+ * @param title action item title
+ * @param icon {@link Drawable} action item icon
+ * @param listener {@link View.OnClickListener} action item listener
+ * @return action item {@link View}
+ */
+ private View getActionItem(String title, Drawable icon, OnClickListener listener) {
+ LinearLayout container = (LinearLayout) inflater.inflate(R.layout.action_item, null);
+
+ ImageView img = (ImageView) container.findViewById(R.id.icon);
+ TextView text = (TextView) container.findViewById(R.id.title);
+
+ if (icon != null) {
+ img.setImageDrawable(icon);
+ }
+
+ if (title != null) {
+ text.setText(title);
+ }
+
+ if (listener != null) {
+ container.setOnClickListener(listener);
+ }
+
+ return container;
+ }
+
+ /**
+ * Show arrow
+ *
+ * @param whichArrow arrow type resource id
+ * @param requestedX distance from left screen
+ */
+ private void showArrow(int whichArrow, int requestedX) {
+ final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
+ final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
+
+ final int arrowWidth = mArrowUp.getMeasuredWidth();
+
+ showArrow.setVisibility(View.VISIBLE);
+
+ ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
+
+ param.leftMargin = requestedX - arrowWidth / 2;
+
+ hideArrow.setVisibility(View.INVISIBLE);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedText.java b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedText.java
new file mode 100644
index 0000000..287834e
--- /dev/null
+++ b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedText.java
@@ -0,0 +1,83 @@
+package roman10reborn.threelinesiconifiedlist;
+
+import android.graphics.drawable.Drawable;
+
+public class ThreeLinesIconifiedText implements Comparable{
+ private String mTextLine1 = "";
+ private String mTextLine2 = "";
+ private String mTextLine3 = "";
+ private Drawable mIcon;
+ private String mIconText = "";
+ private boolean mSelectable = true;
+
+ public ThreeLinesIconifiedText(String _iconLine, String _line1, String _line2, String _line3, Drawable bullet) {
+ mIcon = bullet;
+ mIconText = _iconLine;
+ mTextLine1 = _line1;
+ mTextLine2 = _line2;
+ mTextLine3 = _line3;
+ }
+
+
+ public boolean isSelectable() {
+ return mSelectable;
+ }
+
+ public void setSelectable(boolean selectable) {
+ mSelectable = selectable;
+ }
+
+ public String getIconText() {
+ return mIconText;
+ }
+
+ public String getTextLine1() {
+ return mTextLine1;
+ }
+
+ public String getTextLine2() {
+ return mTextLine2;
+ }
+
+ public String getTextLine3() {
+ return mTextLine3;
+ }
+
+ public void setIconText(String text) {
+ mIconText = text;
+ }
+
+ public void setTextLine1(String text) {
+ mTextLine1 = text;
+ }
+
+ public void setTextLine2(String text) {
+ mTextLine2 = text;
+ }
+
+ public void setTextLine3(String text) {
+ mTextLine3 = text;
+ }
+
+ public void setIcon(Drawable icon) {
+ mIcon = icon;
+ }
+
+ public Drawable getIcon() {
+ return mIcon;
+ }
+ //compare two objects
+ public int compareTo(ThreeLinesIconifiedText other) {
+ int l_firstCompare = this.mTextLine1.compareTo(other.mTextLine1);
+ if (l_firstCompare!=0) {
+ return l_firstCompare;
+ } else {
+ int l_secondCompare = this.mTextLine2.compareTo(other.mTextLine2);
+ if (l_secondCompare!=0) {
+ return l_secondCompare;
+ } else {
+ return this.mTextLine3.compareTo(other.mTextLine3);
+ }
+ }
+ }
+}
diff --git a/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextListAdapter.java b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextListAdapter.java
new file mode 100644
index 0000000..1911893
--- /dev/null
+++ b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextListAdapter.java
@@ -0,0 +1,56 @@
+package roman10reborn.threelinesiconifiedlist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+public class ThreeLinesIconifiedTextListAdapter extends BaseAdapter {
+ private Context mContext;
+
+ private List mItems = new ArrayList();
+
+ public ThreeLinesIconifiedTextListAdapter(Context context) {
+ mContext = context;
+ }
+
+ public void setListItems(List lit)
+ { mItems = lit; }
+
+ public int getCount() { return mItems.size(); }
+
+ public Object getItem(int position)
+ { return mItems.get(position); }
+
+ public boolean areAllItemsSelectable() { return false; }
+
+ public boolean isSelectable(int position) {
+ return mItems.get(position).isSelectable();
+ }
+
+ /** Use the array index as a unique id. */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /** @param convertView The old view to overwrite, if one is passed
+ * @returns a IconifiedTextView that holds wraps around an IconifiedText */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ThreeLinesIconifiedTextView btv;
+ if (convertView == null) {
+ btv = new ThreeLinesIconifiedTextView(mContext, mItems.get(position));
+ } else { //Reuse/Overwrite the View passed
+ // We are assuming(!) that it is castable!
+ btv = (ThreeLinesIconifiedTextView) convertView;
+ btv.setTextLine1(mItems.get(position).getTextLine1());
+ btv.setTextLine2(mItems.get(position).getTextLine2());
+ btv.setTextLine3(mItems.get(position).getTextLine3());
+ btv.setIconText(mItems.get(position).getIconText());
+ btv.setIcon(mItems.get(position).getIcon());
+ }
+ return btv;
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextView.java b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextView.java
new file mode 100644
index 0000000..6bcd019
--- /dev/null
+++ b/src/roman10reborn/threelinesiconifiedlist/ThreeLinesIconifiedTextView.java
@@ -0,0 +1,71 @@
+package roman10reborn.threelinesiconifiedlist;
+
+import roman10reborn.apl.main.R;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+public class ThreeLinesIconifiedTextView extends RelativeLayout {
+ private TextView mTextLine1;
+ private TextView mTextLine2;
+ private TextView mTextLine3;
+ private ImageView mIcon;
+ private TextView mIconText;
+
+ public ThreeLinesIconifiedTextView(Context context, ThreeLinesIconifiedText aIconifiedText) {
+ super(context);
+
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.three_lines_icon_text_view, this, true);
+
+ mIcon = (ImageView) findViewById(R.id.three_lines_icon_text_view_icon);
+ mIcon.setPadding(5, 5, 20, 3); // left, top, right, bottom
+ mIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ //mIcon.setLayoutParams(new LayoutParams(72, 72));
+ mIcon.setImageDrawable(aIconifiedText.getIcon());
+
+ mIconText = (TextView) findViewById(R.id.three_lines_icon_text_view_line_under_icon);
+ //mIconText.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mIconText.setText(aIconifiedText.getIconText());
+
+ mTextLine1 = (TextView) findViewById(R.id.three_lines_icon_text_view_line1);
+ //mTextLine1.setTypeface(Typeface.DEFAULT_BOLD, 0);
+ mTextLine1.setText(aIconifiedText.getTextLine1());
+
+ mTextLine2 = (TextView) findViewById(R.id.three_lines_icon_text_view_line2);
+ //mTextLine2.setTypeface(Typeface.SERIF, 0);
+ mTextLine2.setText(aIconifiedText.getTextLine2());
+
+ mTextLine3 = (TextView) findViewById(R.id.three_lines_icon_text_view_line3);
+ //mTextLine3.setTypeface(Typeface.SERIF, 0);
+ mTextLine3.setText(aIconifiedText.getTextLine3());
+ }
+
+ public void setTextLine1(String words) {
+ mTextLine1.setText(words);
+ }
+
+ public void setTextLine2(String words) {
+ mTextLine2.setText(words);
+ }
+
+ public void setTextLine3(String words) {
+ mTextLine3.setText(words);
+ }
+
+ public void setIconText(String words) {
+ mIconText.setText(words);
+ }
+
+ public void setIcon(Drawable bullet) {
+ mIcon.setImageDrawable(bullet);
+ }
+
+ public void setIcon(int res_id) {
+ mIcon.setImageResource(res_id);
+ }
+}
\ No newline at end of file
diff --git a/src/roman10reborn/utils/ConstantStatic.java b/src/roman10reborn/utils/ConstantStatic.java
new file mode 100644
index 0000000..8e8451e
--- /dev/null
+++ b/src/roman10reborn/utils/ConstantStatic.java
@@ -0,0 +1,6 @@
+package roman10reborn.utils;
+
+public class ConstantStatic {
+ public static String NOTAVAIL = "Not Available";
+ public static String UNKNOWN = "Unknown";
+}
\ No newline at end of file
diff --git a/src/roman10reborn/utils/ContactPhotoLoader.java b/src/roman10reborn/utils/ContactPhotoLoader.java
new file mode 100644
index 0000000..db2762e
--- /dev/null
+++ b/src/roman10reborn/utils/ContactPhotoLoader.java
@@ -0,0 +1,401 @@
+package roman10reborn.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.Handler.Callback;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Contacts.Photo;
+import android.widget.ImageView;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Asynchronously loads contact photos and maintains cache of photos. The class is
+ * mostly single-threaded. The only two methods accessed by the loader thread are
+ * {@link #cacheBitmap} and {@link #obtainPhotoIdsToLoad}. Those methods access concurrent
+ * hash maps shared with the main thread.
+ */
+public class ContactPhotoLoader implements Callback {
+
+ private static final String LOADER_THREAD_NAME = "ContactPhotoLoader";
+
+ /**
+ * Type of message sent by the UI thread to itself to indicate that some photos
+ * need to be loaded.
+ */
+ private static final int MESSAGE_REQUEST_LOADING = 1;
+
+ /**
+ * Type of message sent by the loader thread to indicate that some photos have
+ * been loaded.
+ */
+ private static final int MESSAGE_PHOTOS_LOADED = 2;
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ private final String[] COLUMNS = new String[] { Photo._ID, Contacts.Photo.DATA1};
+
+ /**
+ * The resource ID of the image to be used when the photo is unavailable or being
+ * loaded.
+ */
+ private final int mDefaultResourceId;
+
+ /**
+ * Maintains the state of a particular photo.
+ */
+ private static class BitmapHolder {
+ private static final int NEEDED = 0;
+ private static final int LOADING = 1;
+ private static final int LOADED = 2;
+
+ int state;
+ SoftReference bitmapRef;
+ }
+
+ /**
+ * A soft cache for photos.
+ */
+ private final ConcurrentHashMap mBitmapCache =
+ new ConcurrentHashMap();
+
+ /**
+ * A map from ImageView to the corresponding photo ID. Please note that this
+ * photo ID may change before the photo loading request is started.
+ */
+ private final ConcurrentHashMap mPendingRequests =
+ new ConcurrentHashMap();
+
+ /**
+ * Handler for messages sent to the UI thread.
+ */
+ private final Handler mMainThreadHandler = new Handler(this);
+
+ /**
+ * Thread responsible for loading photos from the database. Created upon
+ * the first request.
+ */
+ private LoaderThread mLoaderThread;
+
+ /**
+ * A gate to make sure we only send one instance of MESSAGE_PHOTOS_NEEDED at a time.
+ */
+ private boolean mLoadingRequested;
+
+ /**
+ * Flag indicating if the image loading is paused.
+ */
+ private boolean mPaused;
+
+ private final Context mContext;
+
+ /**
+ * Constructor.
+ *
+ * @param context content context
+ * @param defaultResourceId the image resource ID to be used when there is
+ * no photo for a contact
+ */
+ public ContactPhotoLoader(Context context, int defaultResourceId) {
+ mDefaultResourceId = defaultResourceId;
+ mContext = context;
+ }
+
+ /**
+ * Load photo into the supplied image view. If the photo is already cached,
+ * it is displayed immediately. Otherwise a request is sent to load the photo
+ * from the database.
+ */
+ public void loadPhoto(ImageView view, long photoId) {
+ if (photoId == 0) {
+ // No photo is needed
+ view.setImageResource(mDefaultResourceId);
+ mPendingRequests.remove(view);
+ } else {
+ boolean loaded = loadCachedPhoto(view, photoId);
+ if (loaded) {
+ mPendingRequests.remove(view);
+ } else {
+ mPendingRequests.put(view, photoId);
+ if (!mPaused) {
+ // Send a request to start loading photos
+ requestLoading();
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the photo is present in cache. If so, sets the photo on the view,
+ * otherwise sets the state of the photo to {@link BitmapHolder#NEEDED} and
+ * temporarily set the image to the default resource ID.
+ */
+ private boolean loadCachedPhoto(ImageView view, long photoId) {
+ BitmapHolder holder = mBitmapCache.get(photoId);
+ if (holder == null) {
+ holder = new BitmapHolder();
+ mBitmapCache.put(photoId, holder);
+ } else if (holder.state == BitmapHolder.LOADED) {
+ // Null bitmap reference means that database contains no bytes for the photo
+ if (holder.bitmapRef == null) {
+ view.setImageResource(mDefaultResourceId);
+ return true;
+ }
+
+ Bitmap bitmap = holder.bitmapRef.get();
+ if (bitmap != null) {
+ view.setImageBitmap(bitmap);
+ return true;
+ }
+
+ // Null bitmap means that the soft reference was released by the GC
+ // and we need to reload the photo.
+ holder.bitmapRef = null;
+ }
+
+ // The bitmap has not been loaded - should display the placeholder image.
+ view.setImageResource(mDefaultResourceId);
+ holder.state = BitmapHolder.NEEDED;
+ return false;
+ }
+
+ /**
+ * Stops loading images, kills the image loader thread and clears all caches.
+ */
+ public void stop() {
+ pause();
+
+ if (mLoaderThread != null) {
+ mLoaderThread.quit();
+ mLoaderThread = null;
+ }
+
+ mPendingRequests.clear();
+ mBitmapCache.clear();
+ }
+
+ public void clear() {
+ mPendingRequests.clear();
+ mBitmapCache.clear();
+ }
+
+ /**
+ * Temporarily stops loading photos from the database.
+ */
+ public void pause() {
+ mPaused = true;
+ }
+
+ /**
+ * Resumes loading photos from the database.
+ */
+ public void resume() {
+ mPaused = false;
+ if (!mPendingRequests.isEmpty()) {
+ requestLoading();
+ }
+ }
+
+ /**
+ * Sends a message to this thread itself to start loading images. If the current
+ * view contains multiple image views, all of those image views will get a chance
+ * to request their respective photos before any of those requests are executed.
+ * This allows us to load images in bulk.
+ */
+ private void requestLoading() {
+ if (!mLoadingRequested) {
+ mLoadingRequested = true;
+ mMainThreadHandler.sendEmptyMessage(MESSAGE_REQUEST_LOADING);
+ }
+ }
+
+ /**
+ * Processes requests on the main thread.
+ */
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_REQUEST_LOADING: {
+ mLoadingRequested = false;
+ if (!mPaused) {
+ if (mLoaderThread == null) {
+ mLoaderThread = new LoaderThread(mContext.getContentResolver());
+ mLoaderThread.start();
+ }
+
+ mLoaderThread.requestLoading();
+ }
+ return true;
+ }
+
+ case MESSAGE_PHOTOS_LOADED: {
+ if (!mPaused) {
+ processLoadedImages();
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Goes over pending loading requests and displays loaded photos. If some of the
+ * photos still haven't been loaded, sends another request for image loading.
+ */
+ private void processLoadedImages() {
+ Iterator iterator = mPendingRequests.keySet().iterator();
+ while (iterator.hasNext()) {
+ ImageView view = iterator.next();
+ long photoId = mPendingRequests.get(view);
+ boolean loaded = loadCachedPhoto(view, photoId);
+ if (loaded) {
+ iterator.remove();
+ }
+ }
+
+ if (!mPendingRequests.isEmpty()) {
+ requestLoading();
+ }
+ }
+
+ /**
+ * Stores the supplied bitmap in cache.
+ */
+ private void cacheBitmap(long id, byte[] bytes) {
+ if (mPaused) {
+ return;
+ }
+
+ BitmapHolder holder = new BitmapHolder();
+ holder.state = BitmapHolder.LOADED;
+ if (bytes != null) {
+ try {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
+ holder.bitmapRef = new SoftReference(bitmap);
+ } catch (OutOfMemoryError e) {
+ // Do nothing - the photo will appear to be missing
+ }
+ }
+ mBitmapCache.put(id, holder);
+ }
+
+ /**
+ * Populates an array of photo IDs that need to be loaded.
+ */
+ private void obtainPhotoIdsToLoad(ArrayList photoIds,
+ ArrayList photoIdsAsStrings) {
+ photoIds.clear();
+ photoIdsAsStrings.clear();
+
+ /*
+ * Since the call is made from the loader thread, the map could be
+ * changing during the iteration. That's not really a problem:
+ * ConcurrentHashMap will allow those changes to happen without throwing
+ * exceptions. Since we may miss some requests in the situation of
+ * concurrent change, we will need to check the map again once loading
+ * is complete.
+ */
+ Iterator iterator = mPendingRequests.values().iterator();
+ while (iterator.hasNext()) {
+ Long id = iterator.next();
+ BitmapHolder holder = mBitmapCache.get(id);
+ if (holder != null && holder.state == BitmapHolder.NEEDED) {
+ // Assuming atomic behavior
+ holder.state = BitmapHolder.LOADING;
+ photoIds.add(id);
+ photoIdsAsStrings.add(id.toString());
+ }
+ }
+ }
+
+ /**
+ * The thread that performs loading of photos from the database.
+ */
+ private class LoaderThread extends HandlerThread implements Callback {
+ private final ContentResolver mResolver;
+ private final StringBuilder mStringBuilder = new StringBuilder();
+ private final ArrayList mPhotoIds = new ArrayList();
+ private final ArrayList mPhotoIdsAsStrings = new ArrayList();
+ private Handler mLoaderThreadHandler;
+
+ public LoaderThread(ContentResolver resolver) {
+ super(LOADER_THREAD_NAME);
+ mResolver = resolver;
+ }
+
+ /**
+ * Sends a message to this thread to load requested photos.
+ */
+ public void requestLoading() {
+ if (mLoaderThreadHandler == null) {
+ mLoaderThreadHandler = new Handler(getLooper(), this);
+ }
+ mLoaderThreadHandler.sendEmptyMessage(0);
+ }
+
+ /**
+ * Receives the above message, loads photos and then sends a message
+ * to the main thread to process them.
+ */
+ public boolean handleMessage(Message msg) {
+ loadPhotosFromDatabase();
+ mMainThreadHandler.sendEmptyMessage(MESSAGE_PHOTOS_LOADED);
+ return true;
+ }
+
+ private void loadPhotosFromDatabase() {
+ obtainPhotoIdsToLoad(mPhotoIds, mPhotoIdsAsStrings);
+
+ int count = mPhotoIds.size();
+ if (count == 0) {
+ return;
+ }
+
+ mStringBuilder.setLength(0);
+ mStringBuilder.append(Photo._ID + " IN(");
+ for (int i = 0; i < count; i++) {
+ if (i != 0) {
+ mStringBuilder.append(',');
+ }
+ mStringBuilder.append('?');
+ }
+ mStringBuilder.append(')');
+
+ Cursor cursor = null;
+ try {
+ cursor = mResolver.query(Data.CONTENT_URI,
+ COLUMNS,
+ mStringBuilder.toString(),
+ mPhotoIdsAsStrings.toArray(EMPTY_STRING_ARRAY),
+ null);
+
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ Long id = cursor.getLong(0);
+ byte[] bytes = cursor.getBlob(1);
+ cacheBitmap(id, bytes);
+ mPhotoIds.remove(id);
+ }
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+
+ // Remaining photos were not found in the database - mark the cache accordingly.
+ count = mPhotoIds.size();
+ for (int i = 0; i < count; i++) {
+ cacheBitmap(mPhotoIds.get(i), null);
+ }
+ }
+ }
+}
diff --git a/src/roman10reborn/utils/ContactsHelperStatic.java b/src/roman10reborn/utils/ContactsHelperStatic.java
new file mode 100644
index 0000000..ea21bc9
--- /dev/null
+++ b/src/roman10reborn/utils/ContactsHelperStatic.java
@@ -0,0 +1,125 @@
+package roman10reborn.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import roman10reborn.apl.main.R;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.PhoneLookup;
+
+public class ContactsHelperStatic {
+ public InputStream openPhoto(Context _context, long contactId) {
+ Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+ Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
+ Cursor cursor = _context.getContentResolver().query(photoUri,
+ new String[] {Contacts.Photo.DATA1}, null, null, null);
+ if (cursor == null) {
+ return null;
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ byte[] data = cursor.getBlob(0);
+ if (data != null) {
+ return new ByteArrayInputStream(data);
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ return null;
+ }
+
+ public static Bitmap getContactsPhotoBitmap(Context _context, long contactId) {
+ Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+ InputStream photoStream = Contacts.openContactPhotoInputStream(
+ _context.getContentResolver(),
+ contactUri);
+ Bitmap photoBitmap = BitmapFactory.decodeStream(photoStream);
+ return photoBitmap;
+ }
+
+ public static Drawable getContactsPhotoDrawable(Context _context, long contactId) {
+ Bitmap l_bitmap = getContactsPhotoBitmap(_context, contactId);
+ if (l_bitmap == null) {
+ l_bitmap = BitmapFactory.decodeResource(_context.getResources(), R.drawable.ic_contact_list_picture);
+ }
+ l_bitmap = framePhoto(_context, l_bitmap);
+ l_bitmap = scaleToAppIconSize(_context, l_bitmap);
+ return new BitmapDrawable(l_bitmap);
+ }
+
+
+ public static Bitmap framePhoto(Context _context, Bitmap photo) {
+ final Resources r = _context.getResources();
+ final Drawable frame = r.getDrawable(R.drawable.photoframe4);
+
+ final int width = r.getDimensionPixelSize(R.dimen.contact_shortcut_frame_width);
+ final int height = r.getDimensionPixelSize(R.dimen.contact_shortcut_frame_height);
+
+ frame.setBounds(0, 0, width, height);
+
+ final Rect padding = new Rect();
+ frame.getPadding(padding);
+
+ final Rect source = new Rect(0, 0, photo.getWidth(), photo.getHeight());
+ final Rect destination = new Rect(padding.left, padding.top,
+ width - padding.right, height - padding.bottom);
+
+ final int d = Math.max(width, height);
+ final Bitmap b = Bitmap.createBitmap(d, d, Bitmap.Config.ARGB_8888);
+ final Canvas c = new Canvas(b);
+
+ c.translate((d - width) / 2.0f, (d - height) / 2.0f);
+ frame.draw(c);
+ c.drawBitmap(photo, source, destination, new Paint(Paint.FILTER_BITMAP_FLAG));
+
+ return b;
+ }
+
+
+ public static Bitmap scaleToAppIconSize(Context _context, Bitmap photo) {
+ int mIconSize = _context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
+ // Setup the drawing classes
+ Bitmap icon = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(icon);
+
+ // Copy in the photo
+ Paint photoPaint = new Paint();
+ photoPaint.setDither(true);
+ photoPaint.setFilterBitmap(true);
+ Rect src = new Rect(0,0, photo.getWidth(),photo.getHeight());
+ Rect dst = new Rect(0,0, mIconSize, mIconSize);
+ canvas.drawBitmap(photo, src, dst, photoPaint);
+
+ return icon;
+ }
+
+
+ public static long getContactIdByPhoneNumber(Context _context, String _number) {
+ final String[] PHONES_PROJECTION = new String[] {
+ PhoneLookup._ID,
+ };
+ final int COLUMN_INDEX_ID = 0;
+ Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(_number));
+ Cursor l_phoneCursor = _context.getContentResolver().query(phoneUri,
+ PHONES_PROJECTION, null, null, null);
+ if (l_phoneCursor != null && l_phoneCursor.moveToFirst()) {
+ return l_phoneCursor.getLong(COLUMN_INDEX_ID);
+ } else {
+ return 0;
+ }
+ }
+}
diff --git a/src/roman10reborn/utils/SortingUtilsStatic.java b/src/roman10reborn/utils/SortingUtilsStatic.java
new file mode 100644
index 0000000..2fcaa0c
--- /dev/null
+++ b/src/roman10reborn/utils/SortingUtilsStatic.java
@@ -0,0 +1,102 @@
+package roman10reborn.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import roman10reborn.apl.data2.AdvancedPhoneLogRecord;
+
+public class SortingUtilsStatic {
+ //sort a list of phone records by date ascending
+ public static void sortRecordsByDateAsc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ return arg0.aplr_time.compareTo(arg1.aplr_time);
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortRecordsByDateDesc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ return arg0.aplr_time.compareTo(arg1.aplr_time)*-1;
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortRecordsByNameAsc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ if (arg0.aplr_name == null) {
+ arg0.aplr_name = ConstantStatic.UNKNOWN;
+ }
+ if (arg1.aplr_name == null) {
+ arg1.aplr_name = ConstantStatic.UNKNOWN;
+ }
+ return arg0.aplr_name.compareTo(arg1.aplr_name);
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortRecordsByNameDesc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ if (arg0.aplr_name == null) {
+ arg0.aplr_name = ConstantStatic.UNKNOWN;
+ }
+ if (arg1.aplr_name == null) {
+ arg1.aplr_name = ConstantStatic.UNKNOWN;
+ }
+ return arg0.aplr_name.compareTo(arg1.aplr_name)*-1;
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortRecordsByDurationAsc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ Integer l_arg0 = new Integer(arg0.aplr_duration);
+ Integer l_arg1 = new Integer(arg1.aplr_duration);
+ return l_arg0.compareTo(l_arg1);
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortRecordsByDurationDesc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(AdvancedPhoneLogRecord arg0,
+ AdvancedPhoneLogRecord arg1) {
+ Integer l_arg0 = new Integer(arg0.aplr_duration);
+ Integer l_arg1 = new Integer(arg1.aplr_duration);
+ return l_arg0.compareTo(l_arg1)*-1;
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+
+ public static void sortStringAsc(ArrayList _records) {
+ Comparator comparator = new Comparator() {
+ public int compare(String arg0,
+ String arg1) {
+ if (arg0 == null) {
+ arg0 = ConstantStatic.UNKNOWN;
+ }
+ if (arg1 == null) {
+ arg1 = ConstantStatic.UNKNOWN;
+ }
+ return arg0.compareTo(arg1);
+ }
+ };
+ Collections.sort(_records, comparator);
+ }
+}
diff --git a/src/roman10reborn/utils/TimeUtilsStatic.java b/src/roman10reborn/utils/TimeUtilsStatic.java
new file mode 100644
index 0000000..84cc640
--- /dev/null
+++ b/src/roman10reborn/utils/TimeUtilsStatic.java
@@ -0,0 +1,16 @@
+package roman10reborn.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class TimeUtilsStatic {
+ public static String dateToStringFormat(Date d) {
+ SimpleDateFormat formater = new SimpleDateFormat("yyyy MMMM dd EEE HH:mm");
+ return formater.format(d);
+ }
+
+ public static String dateToStringFormat2(Date d) {
+ SimpleDateFormat formater = new SimpleDateFormat("yy MMM dd EEE hh:mm a");
+ return formater.format(d);
+ }
+}