summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@android.com>2010-09-28 05:15:08 -0700
committerMichael Chan <mchan@android.com>2010-10-11 11:22:41 -0700
commit352e1a2f834460bd54e03ce94cadd36a46debacb (patch)
treedaa4fba520e34229db5977c584553007f07954f5
parenta821d8bbf1d9e0acdecdc9012bf7dda7982499ad (diff)
downloadandroid_packages_apps_Calendar-352e1a2f834460bd54e03ce94cadd36a46debacb.tar.gz
android_packages_apps_Calendar-352e1a2f834460bd54e03ce94cadd36a46debacb.tar.bz2
android_packages_apps_Calendar-352e1a2f834460bd54e03ce94cadd36a46debacb.zip
Major bug fixing in EventInfo and EditEvent
In EventInfo/Popup: Fixed reminders and response Set a fixed height Renamed Edit event button to Open event in the Event popup Enabled Open event button unless it's a free/busy calendar Removed action bar buttons in Event popup Disallow reminders for busy/free calendars TODO: Update UI only if everything is loaded In Edit Event: Switch to side-by-side label format Have everything ready before removing "Loading" msg Added organizer Restrict adding of attendees: For non-organizers, write permission to the calendar is sufficient. For organizers, the user needs a) write permission to the calendar AND b) ownerCanRespond == true AND c) attendee data exist (this means num of attendees > 1, the calendar owner's and others). TODO: Attendees do not always show up. Need to switch from listview to linear layout TODO: Move to one column format for portrait in EditEvent Turned on Holo.light theme but the light version isn't ready in the framework yet. Removed dependency to android.test.runner b/3052155 b/2709441 b/3060967 b/3060985 Change-Id: I4a25fecf3ade6a7924ba7b55801daced3dca6fa7
-rw-r--r--Android.mk4
-rw-r--r--AndroidManifest.xml3
-rw-r--r--res/layout/edit_event.xml561
-rw-r--r--res/layout/event_info_activity.xml20
-rw-r--r--res/values/strings.xml6
-rw-r--r--res/values/styles.xml8
-rw-r--r--src/com/android/calendar/CalendarEventModel.java15
-rw-r--r--src/com/android/calendar/EventInfoFragment.java146
-rw-r--r--src/com/android/calendar/event/EditEventFragment.java131
-rw-r--r--src/com/android/calendar/event/EditEventHelper.java101
-rw-r--r--src/com/android/calendar/event/EditEventView.java85
11 files changed, 587 insertions, 493 deletions
diff --git a/Android.mk b/Android.mk
index 4d9e73f6..204c290c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -7,10 +7,6 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under,src)
-# TODO: Remove dependency of application on the test runner (android.test.runner)
-# library.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
LOCAL_STATIC_JAVA_LIBRARIES += android-common guava
LOCAL_PACKAGE_NAME := Calendar
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e8f97e4e..95397ff2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -40,9 +40,6 @@
<application android:name="CalendarApplication"
android:label="@string/app_label" android:icon="@drawable/app_icon"
android:taskAffinity="android.task.calendar">
- <!-- TODO: Remove dependency of application on the test runner
- (android.test) library. -->
- <uses-library android:name="android.test.runner" />
<activity
android:name="AllInOneActivity"
diff --git a/res/layout/edit_event.xml b/res/layout/edit_event.xml
index ab1f1cae..e2a2dab6 100644
--- a/res/layout/edit_event.xml
+++ b/res/layout/edit_event.xml
@@ -14,364 +14,329 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/edit_event"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/EditEvent_Layout">
- <TextView android:id="@+id/loading_message"
+ <TextView
+ android:id="@+id/loading_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/loading" />
- <LinearLayout android:id="@+id/two_pane"
- android:orientation="horizontal"
+ <ScrollView
+ android:id="@+id/scroll_view"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <ScrollView
- android:id="@+id/scroll_view"
+ android:layout_height="0dip"
+ android:layout_weight="2"
+ android:fillViewport="true"
+ android:visibility="gone">
+
+ <LinearLayout
+ android:id="@+id/two_pane"
+ android:orientation="horizontal"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:fillViewport="true"
- android:visibility="gone">
+ android:layout_height="match_parent">
- <LinearLayout android:id="@+id/event"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ <!-- LEFT PANE -->
+ <TableLayout
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:stretchColumns="1"
+ android:shrinkColumns="1">
<!-- CALENDARS -->
- <LinearLayout android:id="@+id/calendar_group"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
+ <TableRow
+ android:id="@+id/calendar_group">
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@+id/calendars_label"
android:text="@string/edit_event_calendar_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Spinner android:id="@+id/calendars"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:prompt="@string/edit_event_calendar_label"/>
-
- </LinearLayout>
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Spinner
+ android:id="@+id/calendars"
+ android:prompt="@string/edit_event_calendar_label" />
+ </TableRow>
<!-- WHAT -->
- <TextView android:id="@+id/what_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/what_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <EditText android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/hint_what"
- android:capitalize="sentences"/>
-
- <!-- WHEN -->
- <TextView android:id="@+id/from_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/edit_event_from_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <Button android:id="@+id/start_date"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="7"
- android:gravity="left|center_vertical"
- style="?android:attr/textAppearanceMedium"/>
-
- <Button android:id="@+id/start_time"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="4"
- android:gravity="left|center_vertical"
- style="?android:attr/textAppearanceMedium"/>
-
- </LinearLayout>
-
- <TextView android:id="@+id/to_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/edit_event_to_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <Button android:id="@+id/end_date"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="7"
- android:gravity="left|center_vertical"
- style="?android:attr/textAppearanceMedium"/>
-
- <Button android:id="@+id/end_time"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="4"
+ <TableRow>
+ <TextView
+ android:id="@+id/what_label"
+ android:text="@string/what_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <EditText
+ android:id="@+id/title"
+ android:hint="@string/hint_what"
+ android:capitalize="sentences" />
+ </TableRow>
+
+ <!-- FROM -->
+ <TableRow>
+ <TextView
+ android:id="@+id/from_label"
+ android:text="@string/edit_event_from_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <LinearLayout
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/start_date"
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_weight="7"
+ android:gravity="left|center_vertical"
+ style="?android:attr/textAppearanceMedium" />
+ <Button
+ android:id="@+id/start_time"
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_weight="4"
+ android:gravity="left|center_vertical"
+ style="?android:attr/textAppearanceMedium" />
+ </LinearLayout>
+ </TableRow>
+
+ <!-- TO -->
+ <TableRow>
+ <TextView
+ android:id="@+id/to_label"
+ android:text="@string/edit_event_to_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <LinearLayout
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/end_date"
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_weight="7"
+ android:gravity="left|center_vertical"
+ style="?android:attr/textAppearanceMedium" />
+ <Button
+ android:id="@+id/end_time"
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_weight="4"
+ android:gravity="left|center_vertical"
+ style="?android:attr/textAppearanceMedium" />
+ </LinearLayout>
+ </TableRow>
+
+ <!-- TIME ZONE -->
+ <TableRow>
+ <TextView
+ android:id="@+id/timezone_label"
+ android:text="@string/timezone_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Button
+ android:id="@+id/timezone"
android:gravity="left|center_vertical"
- style="?android:attr/textAppearanceMedium"/>
-
- </LinearLayout>
-
- <TextView android:id="@+id/timezone_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/timezone_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Button android:id="@+id/timezone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="left|center_vertical"
- style="?android:attr/textAppearanceMedium"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical|right"
- android:paddingBottom="5dip">
+ style="?android:attr/textAppearanceMedium" />
+ </TableRow>
+ <!-- ALL DAY -->
+ <TableRow>
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
android:text="@string/edit_event_all_day_label"
- android:paddingTop="1dip"
- android:paddingRight="7dip"
- style="?android:attr/textAppearanceMedium"/>
-
- <CheckBox android:id="@+id/is_all_day"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="15dip"
- android:paddingBottom="15dip"
- android:paddingRight="1dip"/>
-
- </LinearLayout>
+ style="@style/TextAppearance.EditEvent_Label"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical" />
+ <CheckBox
+ android:id="@+id/is_all_day"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical" />
+ </TableRow>
<!-- WHERE -->
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="@android:drawable/divider_horizontal_bright" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/where_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <EditText android:id="@+id/location"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/hint_where"
- android:capitalize="sentences"/>
+ <TableRow>
+ <TextView
+ android:text="@string/where_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <EditText
+ android:id="@+id/location"
+ android:singleLine="true"
+ android:hint="@string/hint_where" />
+ </TableRow>
<!-- DESCRIPTION -->
- <TextView android:id="@+id/description_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/description_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <EditText android:id="@+id/description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/hint_description"
- android:capitalize="sentences"/>
+ <TableRow>
+ <TextView
+ android:id="@+id/description_label"
+ android:text="@string/description_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <EditText
+ android:id="@+id/description"
+ android:layout_width="wrap_content"
+ android:hint="@string/hint_description"
+ android:capitalize="sentences" />
+ </TableRow>
<!-- REPEATS -->
- <TextView android:id="@+id/repeats_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/repeats_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Spinner android:id="@+id/repeats"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:prompt="@string/repeats_label"/>
-
- <!-- MORE OPTIONS -->
- <!-- PRESENCE -->
- <TextView android:id="@+id/presence_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/presence_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Spinner android:id="@+id/availability"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:entries="@array/availability"
- android:prompt="@string/presence_label"/>
+ <TableRow>
+ <TextView
+ android:id="@+id/repeats_label"
+ android:text="@string/repeats_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Spinner
+ android:id="@+id/repeats"
+ android:prompt="@string/repeats_label" />
+ </TableRow>
+
+ <!-- PRESENCE - Show me as [busy | available] -->
+ <TableRow>
+ <TextView
+ android:id="@+id/presence_label"
+ android:text="@string/presence_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Spinner
+ android:id="@+id/availability"
+ android:entries="@array/availability"
+ android:prompt="@string/presence_label" />
+ </TableRow>
<!-- PRIVACY -->
- <TextView android:id="@+id/privacy_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/privacy_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Spinner android:id="@+id/visibility"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:entries="@array/visibility"
- android:prompt="@string/privacy_label"/>
+ <TableRow>
+ <TextView
+ android:id="@+id/privacy_label"
+ android:text="@string/privacy_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Spinner
+ android:id="@+id/visibility"
+ android:entries="@array/visibility"
+ android:prompt="@string/privacy_label" />
+ </TableRow>
<!-- REMINDERS -->
- <View android:id="@+id/reminders_separator"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="@android:drawable/divider_horizontal_dark" />
-
- <TextView android:id="@+id/reminders_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/reminders_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <LinearLayout android:id="@+id/reminder_items_container"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical|right"
- android:paddingBottom="5dip">
-
+ <TableRow>
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="2dip"
- android:text="@string/add_new_reminder"
- style="?android:attr/textAppearanceSmall"/>
-
- <ImageButton android:id="@+id/reminder_add"
- style="@style/PlusButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="7dip"
- android:gravity="center_vertical|right" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- </ScrollView>
-
- <!-- GUESTS/ATTENDEES -->
- <LinearLayout android:id="@+id/attendees_group"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginLeft="4dip"
- android:layout_weight="2" >
-
- <!-- RESPONSE -->
-
- <TextView android:id="@+id/response_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/view_event_response_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <Spinner android:id="@+id/response_value"
- style="?android:attr/textAppearanceMedium"
- android:prompt="@string/view_event_response_label"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:entries="@array/response_labels1"/>
-
- <!-- GUEST LIST -->
- <TextView
- android:layout_width="wrap_content"
+ android:id="@+id/reminders_label"
+ android:text="@string/reminders_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <LinearLayout
+ android:orientation="horizontal">
+ <LinearLayout
+ android:id="@+id/reminder_items_container"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical" />
+ <ImageButton
+ android:id="@+id/reminder_add"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/PlusButton"
+ android:gravity="center_vertical|right" />
+ </LinearLayout>
+ </TableRow>
+ </TableLayout>
+
+ <!-- RIGHT PANE GUESTS/ATTENDEES -->
+ <TableLayout
+ android:id="@+id/attendees_group"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:text="@string/attendees_label"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <LinearLayout android:id="@+id/add_guests_container"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <MultiAutoCompleteTextView android:id="@+id/attendees"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textEmailAddress|textMultiLine"
- android:hint="@string/hint_attendees"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="6dip"
- android:imeOptions="actionNext"
- android:layout_weight="1"
- style="@style/TextAppearance.EditEvent_Label"/>
-
- <ImageButton android:id="@+id/attendee_add"
- style="@style/PlusButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- </LinearLayout>
-
- <ListView
- android:id="@+id/attendee_list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:cacheColorHint="@android:color/background_light"/>
+ android:layout_weight="1"
+ android:stretchColumns="1"
+ android:shrinkColumns="1">
+ <!-- RESPONSE -->
+ <TableRow>
+ <TextView
+ android:id="@+id/response_label"
+ android:text="@string/view_event_response_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <Spinner
+ android:id="@+id/response_value"
+ style="?android:attr/textAppearanceMedium"
+ android:prompt="@string/view_event_response_label"
+ android:entries="@array/response_labels1" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:id="@+id/organizer_label"
+ android:text="@string/view_event_organizer_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <TextView
+ android:id="@+id/organizer" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:id="@+id/add_attendees_label"
+ android:text="@string/add_guests_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+ <LinearLayout
+ android:id="@+id/add_attendees_group"
+ android:orientation="horizontal">
+ <!-- ATTENDEES INPUT -->
+ <MultiAutoCompleteTextView
+ android:id="@+id/attendees"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="textEmailAddress|textMultiLine"
+ android:hint="@string/hint_attendees"
+ android:imeOptions="actionNext" />
+
+ <!-- ATTENDEES ADD BUTTON -->
+ <ImageButton
+ android:id="@+id/add_attendee_button"
+ style="@style/PlusButton"
+ android:layout_gravity="right"
+ android:enabled="false"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ </TableRow>
+
+ <!-- ATTENDEES -->
+ <TableRow>
+ <TextView
+ android:text="@string/attendees_label"
+ style="@style/TextAppearance.EditEvent_Label" />
+
+ <!-- GUEST LIST -->
+ <ListView
+ android:id="@+id/attendee_list"
+ android:orientation="vertical">
+ </ListView>
+ </TableRow>
+ </TableLayout>
</LinearLayout>
-
- </LinearLayout>
+ </ScrollView>
<!-- BUTTONS -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@android:style/ButtonBar" >
+ style="@android:style/ButtonBar">
- <Button android:id="@+id/save"
+ <Button
+ android:id="@+id/save"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/save_label" />
- <Button android:id="@+id/discard"
+ <Button
+ android:id="@+id/discard"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/discard_label" />
- <Button android:id="@+id/delete"
+ <Button
+ android:id="@+id/delete"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/delete_label" />
</LinearLayout>
-
</LinearLayout>
diff --git a/res/layout/event_info_activity.xml b/res/layout/event_info_activity.xml
index f550c2b4..c3a9587f 100644
--- a/res/layout/event_info_activity.xml
+++ b/res/layout/event_info_activity.xml
@@ -16,12 +16,11 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+ android:orientation="vertical"
android:background="#fafafa"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="4dip"
- android:layout_alignParentTop="true">
+ android:layout_height="match_parent"
+ android:padding="4dip">
<LinearLayout
android:id="@+id/event"
@@ -104,7 +103,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="5dip"
android:text="@string/view_event_organizer_label"
style="?android:attr/textAppearanceMedium" />
@@ -119,7 +117,8 @@
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="1"
android:paddingTop="16dip"
android:paddingBottom="12dip"
android:autoLink="all"
@@ -155,6 +154,8 @@
android:id="@+id/attendee_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
android:paddingTop="4dip"
style="?android:attr/textAppearanceMedium" />
@@ -164,7 +165,8 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="4dip">
+ android:paddingTop="4dip"
+ android:visibility="gone">
<TextView
android:id="@+id/reminders_label"
@@ -212,8 +214,8 @@
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:visibility="gone"
- android:text="@string/event_edit" />
+ android:enabled="false"
+ android:text="@string/edit_event_label" />
<Button
android:id="@+id/done"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8c2d149e..e078e78f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -246,6 +246,8 @@
<string name="no_calendars_found">Before you can add an event, you must add at least one Calendar account to the device. Touch \u0022Add account\u0022 to add an account. Or if you just added an account, wait for it to finish syncing and try again.</string>
<!-- Title of a button shown when there is no account available and the system prompt a user to add one. [CHAR LIMIT=none] -->
<string name="add_account">Add account</string>
+ <!-- Label for adding guests to an event [CHAR LIMIT=32]-->
+ <string name="add_guests_label">Add guests</string>
<!-- View Event -->
<skip />
@@ -285,8 +287,8 @@
<!-- Button labels: -->
<skip />
<!-- This is the title of a popup window that is displayed when the user
- edits a repeating event. -->
- <string name="edit_event_label">"Edit event"</string>
+ edits a repeating event. [CHAR LIMIT=20]-->
+ <string name="edit_event_label">"Open event"</string>
<!-- The button label for deleting an event -->
<string name="delete_label">"Delete"</string>
<!-- A menu item for deleting an event -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 797a22db..7418f565 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -59,7 +59,11 @@
<style name="TextAppearance.EditEvent_Label">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
<item name="android:textStyle">bold</item>
- <item name="android:paddingLeft">2dip</item>
+ <item name="android:gravity">top|left</item>
+ <item name="android:minHeight">48dip</item>
+ <item name="android:maxWidth">200dip</item>
+ <item name="android:paddingLeft">16dip</item>
+ <item name="android:paddingRight">16dip</item>
</style>
<style name="TextAppearance.EventInfo_Label">
@@ -91,7 +95,7 @@
<item name="android:windowContentOverlay">@null</item>
</style>
- <style name="CalendarTheme.WithActionBar">
+ <style name="CalendarTheme.WithActionBar" parent="android:Theme.Light.Holo">
<item name="android:windowNoTitle">false</item>
<item name="android:windowActionBar">true</item>
</style>
diff --git a/src/com/android/calendar/CalendarEventModel.java b/src/com/android/calendar/CalendarEventModel.java
index 3d382bde..b9b531d9 100644
--- a/src/com/android/calendar/CalendarEventModel.java
+++ b/src/com/android/calendar/CalendarEventModel.java
@@ -87,6 +87,10 @@ public class CalendarEventModel {
public String mDescription = null;
public String mRrule = null;
public String mOrganizer = null;
+ public String mOrganizerDisplayName = null;
+ /**
+ * Read-Only - Derived from other fields
+ */
public boolean mIsOrganizer = true;
public boolean mIsFirstEventInSeries = true;
@@ -118,6 +122,16 @@ public class CalendarEventModel {
public boolean mGuestsCanInviteOthers = false;
public boolean mGuestsCanSeeGuests = false;
+// NEW vvvvvvvvvvvvvvv
+ // FRAG_TODO update equal/hashcode/clear
+ public boolean mOrganizerCanRespond = false;
+ public int mCalendarAccessLevel = 0;
+
+ // The model can't be updated with a calendar cursor until it has been
+ // updated with an event cursor.
+ public boolean mModelUpdatedWithEventCursor;
+// NEW ^^^^^^^^^^^^^
+
public int mVisibility = 0;
public ArrayList<Integer> mReminderMinutes;
@@ -219,6 +233,7 @@ public class CalendarEventModel {
mDescription = null;
mRrule = null;
mOrganizer = null;
+ mOrganizerDisplayName = null;
mIsOrganizer = true;
mIsFirstEventInSeries = true;
diff --git a/src/com/android/calendar/EventInfoFragment.java b/src/com/android/calendar/EventInfoFragment.java
index 4c83f893..1bcb05ef 100644
--- a/src/com/android/calendar/EventInfoFragment.java
+++ b/src/com/android/calendar/EventInfoFragment.java
@@ -66,9 +66,6 @@ import android.text.util.Rfc822Token;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@@ -201,14 +198,6 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
Reminders.METHOD_DEFAULT + ")";
private static final String REMINDERS_SORT = Reminders.MINUTES;
- private static final int MENU_GROUP_REMINDER = 1;
- private static final int MENU_GROUP_EDIT = 2;
- private static final int MENU_GROUP_DELETE = 3;
-
- private static final int MENU_ADD_REMINDER = 1;
- private static final int MENU_EDIT = 2;
- private static final int MENU_DELETE = 3;
-
private View mView;
private LinearLayout mRemindersContainer;
private LinearLayout mOrganizerContainer;
@@ -226,7 +215,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
private boolean mHasAttendeeData;
private boolean mIsOrganizer;
private long mCalendarOwnerAttendeeId = EditEventHelper.ATTENDEE_ID_NONE;
- private boolean mOrganizerCanRespond;
+ private boolean mOwnerCanRespond;
private String mCalendarOwnerAccount;
private boolean mCanModifyCalendar;
private boolean mIsBusyFreeCalendar;
@@ -293,7 +282,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
};
private static final int DIALOG_WIDTH = 500; // FRAG_TODO scale
- private static final int DIALOG_HEIGHT = 500;
+ private static final int DIALOG_HEIGHT = 600;
private boolean mIsDialog = false;
private int mX = -1;
private int mY = -1;
@@ -339,22 +328,26 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
// update the action bar since our option set might have changed
activity.invalidateOptionsMenu();
- // this is used for both attendees and reminders
- args = new String[] { Long.toString(mEventId) };
-
- // start attendees query
- uri = Attendees.CONTENT_URI;
- startQuery(TOKEN_QUERY_ATTENDEES, null, uri, ATTENDEES_PROJECTION,
- ATTENDEES_WHERE, args, ATTENDEES_SORT_ORDER);
-
- // start reminders query
- mOriginalHasAlarm = mEventCursor.getInt(EVENT_INDEX_HAS_ALARM) != 0;
- if (mOriginalHasAlarm) {
- uri = Reminders.CONTENT_URI;
- startQuery(TOKEN_QUERY_REMINDERS, null, uri, REMINDERS_PROJECTION,
- REMINDERS_WHERE, args, REMINDERS_SORT);
+ if (!mIsBusyFreeCalendar) {
+ // this is used for both attendees and reminders
+ args = new String[] { Long.toString(mEventId) };
+
+ // start attendees query
+ uri = Attendees.CONTENT_URI;
+ startQuery(TOKEN_QUERY_ATTENDEES, null, uri, ATTENDEES_PROJECTION,
+ ATTENDEES_WHERE, args, ATTENDEES_SORT_ORDER);
+
+ // start reminders query
+ mOriginalHasAlarm = mEventCursor.getInt(EVENT_INDEX_HAS_ALARM) != 0;
+ if (mOriginalHasAlarm) {
+ uri = Reminders.CONTENT_URI;
+ startQuery(TOKEN_QUERY_REMINDERS, null, uri, REMINDERS_PROJECTION,
+ REMINDERS_WHERE, args, REMINDERS_SORT);
+ } else {
+ // if no reminders, hide the appropriate fields
+ updateRemindersVisibility();
+ }
} else {
- // if no reminders, hide the appropriate fields
updateRemindersVisibility();
}
break;
@@ -450,6 +443,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
a.dimAmount = .4f;
a.width = DIALOG_WIDTH;
+ a.height = DIALOG_HEIGHT;
if (mX != -1 || mY != -1) {
a.x = mX - a.width - 64; // FRAG_TODO event sender should return the left edge or a rect
@@ -507,7 +501,6 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
public void onAttach(Activity activity) {
super.onAttach(activity);
mEditResponseHelper = new EditResponseHelper(activity);
- setHasOptionsMenu(true);
mHandler = new QueryHandler(activity);
mPresenceQueryHandler = new PresenceQueryHandler(activity, activity.getContentResolver());
}
@@ -547,7 +540,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
ImageButton reminderAddButton = (ImageButton) mView.findViewById(R.id.reminder_add);
reminderAddButton.setOnClickListener(addReminderOnClickListener);
-//CLEANUP mReminderAdder = (LinearLayout) mView.findViewById(R.id.reminder_adder);
+ mReminderAdder = (LinearLayout) mView.findViewById(R.id.reminder_adder);
if (mUri == null) {
// restore event ID from bundle
@@ -751,74 +744,13 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
updateRemindersVisibility();
}
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- MenuItem item;
- item = menu.add(MENU_GROUP_REMINDER, MENU_ADD_REMINDER, 0,
- R.string.add_new_reminder);
- item.setIcon(R.drawable.ic_menu_reminder);
- item.setAlphabeticShortcut('r');
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-
- item = menu.add(MENU_GROUP_EDIT, MENU_EDIT, 0, R.string.edit_event_label);
- item.setIcon(android.R.drawable.ic_menu_edit);
- item.setAlphabeticShortcut('e');
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-
- item = menu.add(MENU_GROUP_DELETE, MENU_DELETE, 0, R.string.delete_event_label);
- item.setIcon(android.R.drawable.ic_menu_delete);
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-
- super.onCreateOptionsMenu(menu, inflater);
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- boolean canAddReminders = canAddReminders();
- menu.setGroupVisible(MENU_GROUP_REMINDER, canAddReminders);
- menu.setGroupEnabled(MENU_GROUP_REMINDER, canAddReminders);
-
- menu.setGroupVisible(MENU_GROUP_EDIT, mCanModifyEvent);
- menu.setGroupEnabled(MENU_GROUP_EDIT, mCanModifyEvent);
- menu.setGroupVisible(MENU_GROUP_DELETE, mCanModifyCalendar);
- menu.setGroupEnabled(MENU_GROUP_DELETE, mCanModifyCalendar);
-
- super.onPrepareOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- super.onOptionsItemSelected(item);
- switch (item.getItemId()) {
- case MENU_ADD_REMINDER:
- addReminder();
- break;
- case MENU_EDIT:
- doEdit();
- break;
- case MENU_DELETE:
- doDelete();
- break;
- }
- return true;
- }
-
-//CLEANUP @Override
-// public boolean onKeyDown(int keyCode, KeyEvent event) {
-// if (keyCode == KeyEvent.KEYCODE_DEL) {
-// doDelete();
-// return true;
-// }
-// return super.onKeyDown(keyCode, event);
-// }
-
private void updateRemindersVisibility() {
-//CLEANUP if (mIsBusyFreeCalendar) {
-// mRemindersContainer.setVisibility(View.GONE);
-// } else {
-// mRemindersContainer.setVisibility(View.VISIBLE);
-// mReminderAdder.setVisibility(canAddReminders() ? View.VISIBLE : View.GONE);
-// }
+ if (mIsBusyFreeCalendar) {
+ mRemindersContainer.setVisibility(View.GONE);
+ } else {
+ mRemindersContainer.setVisibility(View.VISIBLE);
+ mReminderAdder.setVisibility(canAddReminders() ? View.VISIBLE : View.GONE);
+ }
}
/**
@@ -1050,9 +982,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
}
// Description
- if (description == null || description.length() == 0) {
- setVisibilityCommon(view, R.id.description, View.GONE);
- } else {
+ if (description != null && description.length() != 0) {
setTextCommon(view, R.id.description, description);
}
}
@@ -1063,7 +993,7 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
mCalendarsCursor.moveToFirst();
String tempAccount = mCalendarsCursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT);
mCalendarOwnerAccount = (tempAccount == null) ? "" : tempAccount;
- mOrganizerCanRespond = mCalendarsCursor.getInt(CALENDARS_INDEX_OWNER_CAN_RESPOND) != 0;
+ mOwnerCanRespond = mCalendarsCursor.getInt(CALENDARS_INDEX_OWNER_CAN_RESPOND) != 0;
String displayName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME);
@@ -1082,15 +1012,17 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL) == Calendars.FREEBUSY_ACCESS;
mCanModifyEvent = mCanModifyCalendar
&& (mIsOrganizer || (mEventCursor.getInt(EVENT_INDEX_GUESTS_CAN_MODIFY) != 0));
- if (mCanModifyEvent) {
+
+ if (!mIsBusyFreeCalendar) {
Button b = (Button) mView.findViewById(R.id.edit);
+ b.setEnabled(true);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doEdit();
EventInfoFragment.this.dismiss();
- }});
- b.setVisibility(View.VISIBLE);
+ }
+ });
}
} else {
//CLEANUP setVisibilityCommon(view, R.id.calendar_container, View.GONE);
@@ -1291,9 +1223,11 @@ public class EventInfoFragment extends DialogFragment implements View.OnClickLis
// paying attention to whether or not an attendee status was
// included in the feed, but we're currently omitting those corner cases
// for simplicity).
-//CLEANUP
+
+ // TODO Switch to EditEventHelper.canRespond when this class uses CalendarEventModel.
+
if (!mCanModifyCalendar || (mHasAttendeeData && mIsOrganizer && mNumOfAttendees <= 1) ||
- (mIsOrganizer && !mOrganizerCanRespond)) {
+ (mIsOrganizer && !mOwnerCanRespond)) {
setVisibilityCommon(view, R.id.response_container, View.GONE);
return;
}
diff --git a/src/com/android/calendar/event/EditEventFragment.java b/src/com/android/calendar/event/EditEventFragment.java
index bef69201..7ab589bb 100644
--- a/src/com/android/calendar/event/EditEventFragment.java
+++ b/src/com/android/calendar/event/EditEventFragment.java
@@ -58,10 +58,19 @@ public class EditEventFragment extends Fragment implements EventHandler {
private static final boolean DEBUG = false;
- private static final int TOKEN_EVENT = 0;
- private static final int TOKEN_ATTENDEES = 1;
- private static final int TOKEN_REMINDERS = 2;
- private static final int TOKEN_CALENDARS = 3;
+ private static final int TOKEN_EVENT = 1;
+ private static final int TOKEN_ATTENDEES = 1 << 1;
+ private static final int TOKEN_REMINDERS = 1 << 2;
+ private static final int TOKEN_CALENDARS = 1 << 3;
+ private static final int TOKEN_ALL = TOKEN_EVENT | TOKEN_ATTENDEES | TOKEN_REMINDERS
+ | TOKEN_CALENDARS;
+
+ /**
+ * A bitfield of TOKEN_* to keep track which query hasn't been completed
+ * yet. Once all queries have returned, the model can be applied to the
+ * view.
+ */
+ private int mOutstandingQueries;
EditEventHelper mHelper;
CalendarEventModel mModel;
@@ -111,7 +120,8 @@ public class EditEventFragment extends Fragment implements EventHandler {
// The cursor is empty. This can happen if the event
// was deleted.
cursor.close();
- mContext.finish();
+ mOnDone.setDoneCode(Utils.DONE_EXIT);
+ mOnDone.run();
return;
}
mOriginalModel = new CalendarEventModel();
@@ -131,11 +141,8 @@ public class EditEventFragment extends Fragment implements EventHandler {
displayEditWhichDialogue();
eventId = mModel.mId;
- // If there are attendees or alarms query for them
- // We only query one table at a time so that we can easily
- // tell if we are finished with all our queries. At a later
- // point we might want to parallelize this and keep track of
- // which queries are done.
+
+ // TOKEN_ATTENDEES
if (mModel.mHasAttendeeData && eventId != -1) {
Uri attUri = Attendees.CONTENT_URI;
String[] whereArgs = {
@@ -145,7 +152,12 @@ public class EditEventFragment extends Fragment implements EventHandler {
EditEventHelper.ATTENDEES_PROJECTION,
EditEventHelper.ATTENDEES_WHERE /* selection */,
whereArgs /* selection args */, null /* sort order */);
- } else if (mModel.mHasAlarm) {
+ } else {
+ setModelIfDone(TOKEN_ATTENDEES);
+ }
+
+ // TOKEN_REMINDERS
+ if (mModel.mHasAlarm) {
Uri rUri = Reminders.CONTENT_URI;
String[] remArgs = {
Long.toString(eventId), Integer.toString(Reminders.METHOD_ALERT),
@@ -157,10 +169,18 @@ public class EditEventFragment extends Fragment implements EventHandler {
EditEventHelper.REMINDERS_WHERE /* selection */,
remArgs /* selection args */, null /* sort order */);
} else {
- // Set the model if there are no more queries to
- // make
- mView.setModel(mModel);
+ setModelIfDone(TOKEN_REMINDERS);
}
+
+ // TOKEN_CALENDARS
+ String[] selArgs = {
+ Long.toString(mModel.mCalendarId)
+ };
+ mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI,
+ EditEventHelper.CALENDARS_PROJECTION, EditEventHelper.CALENDARS_WHERE,
+ selArgs /* selection args */, null /* sort order */);
+
+ setModelIfDone(TOKEN_EVENT);
break;
case TOKEN_ATTENDEES:
try {
@@ -170,10 +190,21 @@ public class EditEventFragment extends Fragment implements EventHandler {
int status = cursor.getInt(EditEventHelper.ATTENDEES_INDEX_STATUS);
int relationship = cursor
.getInt(EditEventHelper.ATTENDEES_INDEX_RELATIONSHIP);
- if (email != null) {
- if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
+ if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
+ if (email != null) {
mModel.mOrganizer = email;
+ mModel.mIsOrganizer = mModel.mOwnerAccount
+ .equalsIgnoreCase(email);
}
+
+ if (TextUtils.isEmpty(name)) {
+ mModel.mOrganizerDisplayName = mModel.mOrganizer;
+ } else {
+ mModel.mOrganizerDisplayName = name;
+ }
+ }
+
+ if (email != null) {
if (mModel.mOwnerAccount != null &&
mModel.mOwnerAccount.equalsIgnoreCase(email)) {
int attendeeId =
@@ -193,26 +224,8 @@ public class EditEventFragment extends Fragment implements EventHandler {
} finally {
cursor.close();
}
- // This is done after attendees so we know when our
- // model is filled out
- eventId = mModel.mId;
- boolean hasAlarm = mModel.mHasAlarm;
- if (hasAlarm) {
- Uri rUri = Reminders.CONTENT_URI;
- String[] remArgs = {
- Long.toString(eventId), Integer.toString(Reminders.METHOD_ALERT),
- Integer.toString(Reminders.METHOD_DEFAULT)
- };
- mHandler
- .startQuery(TOKEN_REMINDERS, null, rUri,
- EditEventHelper.REMINDERS_PROJECTION,
- EditEventHelper.REMINDERS_WHERE /* selection */,
- remArgs /* selection args */, null /* sort order */);
- } else {
- // Set the model if there are no more queries to
- // make
- mView.setModel(mModel);
- }
+
+ setModelIfDone(TOKEN_ATTENDEES);
break;
case TOKEN_REMINDERS:
try {
@@ -225,24 +238,42 @@ public class EditEventFragment extends Fragment implements EventHandler {
} finally {
cursor.close();
}
- // Set the model after we finish all the necessary
- // queries.
- mView.setModel(mModel);
+
+ setModelIfDone(TOKEN_REMINDERS);
break;
case TOKEN_CALENDARS:
- MatrixCursor matrixCursor = Utils.matrixCursorFromCursor(cursor);
-
- if (DEBUG) {
- Log.d(TAG, "onQueryComplete: setting cursor with "
- + matrixCursor.getCount() + " calendars");
+ try {
+ if (mModel.mCalendarId == -1) {
+ // Populate Calendar spinner only if no calendar is set e.g. new event
+ MatrixCursor matrixCursor = Utils.matrixCursorFromCursor(cursor);
+ if (DEBUG) {
+ Log.d(TAG, "onQueryComplete: setting cursor with "
+ + matrixCursor.getCount() + " calendars");
+ }
+ mView.setCalendarsCursor(matrixCursor, isAdded() && isResumed());
+ } else {
+ // Populate model for an existing event
+ EditEventHelper.setModelFromCalendarCursor(mModel, cursor);
+ }
+ } finally {
+ cursor.close();
}
- mView.setCalendarsCursor(matrixCursor, isAdded() && isResumed());
- cursor.close();
+
+ setModelIfDone(TOKEN_CALENDARS);
break;
}
}
}
+ void setModelIfDone(int queryType) {
+ synchronized (this) {
+ mOutstandingQueries &= ~queryType;
+ if (mOutstandingQueries == 0) {
+ mView.setModel(mModel);
+ }
+ }
+ }
+
public EditEventFragment() {
mEvent = null;
}
@@ -258,6 +289,7 @@ public class EditEventFragment extends Fragment implements EventHandler {
mEnd = -1;
if (mEvent != null) {
if (mEvent.id != -1) {
+ mModel.mId = mEvent.id;
mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEvent.id);
}
if (mEvent.startTime != null) {
@@ -280,19 +312,20 @@ public class EditEventFragment extends Fragment implements EventHandler {
// Kick off the query for the event
boolean newEvent = mUri == null;
if (!newEvent) {
+ mOutstandingQueries = TOKEN_ALL;
if (DEBUG) {
- Log.d(TAG, "onCreate: uri for event is " + mUri.toString());
+ Log.d(TAG, "startQuery: uri for event is " + mUri.toString());
}
mHandler.startQuery(TOKEN_EVENT, null, mUri, EditEventHelper.EVENT_PROJECTION,
null /* selection */, null /* selection args */, null /* sort order */);
} else {
+ mOutstandingQueries = TOKEN_CALENDARS;
if (DEBUG) {
- Log.d(TAG, "onCreate: Editing a new event.");
+ Log.d(TAG, "startQuery: Editing a new event.");
}
mModel.mStart = mBegin;
mModel.mEnd = mEnd;
mModel.mSelfAttendeeStatus = Attendees.ATTENDEE_STATUS_ACCEPTED;
- mView.setModel(mModel);
// Start a query in the background to read the list of calendars
mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI,
diff --git a/src/com/android/calendar/event/EditEventHelper.java b/src/com/android/calendar/event/EditEventHelper.java
index 7e20bf15..33e5cd10 100644
--- a/src/com/android/calendar/event/EditEventHelper.java
+++ b/src/com/android/calendar/event/EditEventHelper.java
@@ -42,6 +42,7 @@ import android.text.format.Time;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.util.Log;
+import android.view.View;
import android.widget.ImageView;
import android.widget.QuickContactBadge;
@@ -78,6 +79,8 @@ public class EditEventHelper {
Events.OWNER_ACCOUNT, // 15
Events.HAS_ATTENDEE_DATA, // 16
Events.ORIGINAL_EVENT, // 17
+ Events.ORGANIZER, // 18
+ Events.GUESTS_CAN_MODIFY, // 19
};
protected static final int EVENT_INDEX_ID = 0;
protected static final int EVENT_INDEX_TITLE = 1;
@@ -97,6 +100,8 @@ public class EditEventHelper {
protected static final int EVENT_INDEX_OWNER_ACCOUNT = 15;
protected static final int EVENT_INDEX_HAS_ATTENDEE_DATA = 16;
protected static final int EVENT_INDEX_ORIGINAL_EVENT = 17;
+ protected static final int EVENT_INDEX_ORGANIZER = 18;
+ protected static final int EVENT_INDEX_GUESTS_CAN_MODIFY = 19;
public static final String[] REMINDERS_PROJECTION = new String[] {
Reminders._ID, // 0
@@ -160,15 +165,23 @@ public class EditEventHelper {
Calendars.DISPLAY_NAME, // 1
Calendars.OWNER_ACCOUNT, // 2
Calendars.COLOR, // 3
+ Calendars.ORGANIZER_CAN_RESPOND, // 4
+ Calendars.ACCESS_LEVEL, // 5
+ Calendars.SELECTED, // 6
};
static final int CALENDARS_INDEX_ID = 0;
static final int CALENDARS_INDEX_DISPLAY_NAME = 1;
static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2;
static final int CALENDARS_INDEX_COLOR = 3;
+ static final int CALENDARS_INDEX_ORGANIZER_CAN_RESPOND = 4;
+ static final int CALENDARS_INDEX_ACCESS_LEVEL = 5;
+ static final int CALENDARS_INDEX_SELECTED = 6;
static final String CALENDARS_WHERE_WRITEABLE_VISIBLE = Calendars.ACCESS_LEVEL + ">="
+ Calendars.CONTRIBUTOR_ACCESS + " AND " + Calendars.SELECTED + "=1";
+ static final String CALENDARS_WHERE = Calendars._ID + "=?";
+
static final String[] ATTENDEES_PROJECTION = new String[] {
Attendees._ID, // 0
Attendees.ATTENDEE_NAME, // 1
@@ -988,6 +1001,9 @@ public class EditEventHelper {
model.mOwnerAccount = cursor.getString(EVENT_INDEX_OWNER_ACCOUNT);
model.mHasAttendeeData = cursor.getInt(EVENT_INDEX_HAS_ATTENDEE_DATA) != 0;
model.mOriginalEvent = cursor.getString(EVENT_INDEX_ORIGINAL_EVENT);
+ model.mOrganizer = cursor.getString(EVENT_INDEX_ORGANIZER);
+ model.mIsOrganizer = model.mOwnerAccount.equalsIgnoreCase(model.mOrganizer);
+ model.mGuestsCanModify = cursor.getInt(EVENT_INDEX_GUESTS_CAN_MODIFY) != 0;
if (visibility > 0) {
// For now the array contains the values 0, 2, and 3. We subtract
@@ -1005,6 +1021,91 @@ public class EditEventHelper {
} else {
model.mEnd = cursor.getLong(EVENT_INDEX_DTEND);
}
+
+ model.mModelUpdatedWithEventCursor = true;
+ }
+
+ /**
+ * Uses a calendar cursor to fill in the given model This method assumes the
+ * cursor used {@link #CALENDARS_PROJECTION} as it's query projection. It uses
+ * the cursor to fill in the given model with all the information available.
+ *
+ * @param model The model to fill in
+ * @param cursor An event cursor that used {@link #CALENDARS_PROJECTION} for the query
+ * @return returns true if model was updated with the info in the cursor.
+ */
+ public static boolean setModelFromCalendarCursor(CalendarEventModel model, Cursor cursor) {
+ if (model == null || cursor == null) {
+ Log.wtf(TAG, "Attempted to build non-existent model or from an incorrect query.");
+ return false;
+ }
+
+ if (model.mCalendarId == -1) {
+ return false;
+ }
+
+ if (!model.mModelUpdatedWithEventCursor) {
+ Log.wtf(TAG,
+ "Can't update model with a Calendar cursor until it has seen an Event cursor.");
+ return false;
+ }
+
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ if (model.mCalendarId != cursor.getInt(EVENT_INDEX_CALENDAR_ID)) {
+ continue;
+ }
+
+ model.mOrganizerCanRespond = cursor.getInt(CALENDARS_INDEX_ORGANIZER_CAN_RESPOND) != 0;
+
+ model.mCalendarAccessLevel = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL);
+
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean canModifyEvent(CalendarEventModel model) {
+ return canModifyCalendar(model)
+ && (model.mIsOrganizer || model.mGuestsCanModify);
+ }
+
+ public static boolean canModifyCalendar(CalendarEventModel model) {
+ return model.mCalendarAccessLevel >= Calendars.CONTRIBUTOR_ACCESS
+ || model.mCalendarId == -1;
+ }
+
+ public static boolean canRespond(CalendarEventModel model) {
+ // For non-organizers, write permission to the calendar is sufficient.
+ // For organizers, the user needs a) write permission to the calendar
+ // AND b) ownerCanRespond == true AND c) attendee data exist
+ // (this means num of attendees > 1, the calendar owner's and others).
+ // Note that mAttendeeList omits the organizer.
+
+ // (there are more cases involved to be 100% accurate, such as
+ // paying attention to whether or not an attendee status was
+ // included in the feed, but we're currently omitting those corner cases
+ // for simplicity).
+
+ if (!canModifyCalendar(model)) {
+ return false;
+ }
+
+ if (!model.mIsOrganizer) {
+ return true;
+ }
+
+ if (!model.mOrganizerCanRespond) {
+ return false;
+ }
+
+ // This means we don't have the attendees data so we can't send
+ // the list of attendees and the status back to the server
+ if (model.mHasAttendeeData && model.mAttendeesList.size() == 0) {
+ return false;
+ }
+
+ return true;
}
/**
diff --git a/src/com/android/calendar/event/EditEventView.java b/src/com/android/calendar/event/EditEventView.java
index 4dd51c1a..ebd935eb 100644
--- a/src/com/android/calendar/event/EditEventView.java
+++ b/src/com/android/calendar/event/EditEventView.java
@@ -53,6 +53,7 @@ import android.text.util.Rfc822Tokenizer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
@@ -79,10 +80,13 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
private static final String TAG = "EditEvent";
+ private static final String GOOGLE_SECONDARY_CALENDAR = "calendar.google.com";
+
private static final int REMINDER_FLING_VELOCITY = 2000;
private LayoutInflater mLayoutInflater;
+ ArrayList<View> mViewList = new ArrayList<View>();
TextView mLoadingMessage;
ScrollView mScrollView;
Button mStartDateButton;
@@ -104,7 +108,6 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
TextView mDescriptionTextView;
TextView mTimezoneTextView;
TextView mTimezoneFooterView;
- View mRemindersSeparator;
LinearLayout mRemindersContainer;
MultiAutoCompleteTextView mAttendeesList;
ImageButton mAddAttendeesButton;
@@ -130,7 +133,6 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
private int mDefaultReminderMinutes;
private boolean mSaveAfterQueryComplete = false;
- private boolean mCalendarsCursorSet = false;
private Time mStartTime;
private Time mEndTime;
@@ -736,23 +738,36 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
mLayoutInflater = activity.getLayoutInflater();
// cache all the widgets
+ mCalendarsSpinner = (Spinner) view.findViewById(R.id.calendars);
+ mViewList.add(mCalendarsSpinner);
mTitleTextView = (TextView) view.findViewById(R.id.title);
+ mViewList.add(mTitleTextView);
mLocationTextView = (TextView) view.findViewById(R.id.location);
+ mViewList.add(mLocationTextView);
mDescriptionTextView = (TextView) view.findViewById(R.id.description);
+ mViewList.add(mDescriptionTextView);
mTimezoneTextView = (TextView) view.findViewById(R.id.timezone_label);
mTimezoneFooterView = (TextView) mLayoutInflater.inflate(R.layout.timezone_footer, null);
mStartDateButton = (Button) view.findViewById(R.id.start_date);
+ mViewList.add(mStartDateButton);
mEndDateButton = (Button) view.findViewById(R.id.end_date);
+ mViewList.add(mEndDateButton);
mStartTimeButton = (Button) view.findViewById(R.id.start_time);
+ mViewList.add(mStartTimeButton);
mEndTimeButton = (Button) view.findViewById(R.id.end_time);
+ mViewList.add(mEndTimeButton);
mTimezoneButton = (Button) view.findViewById(R.id.timezone);
+ mViewList.add(mTimezoneButton);
mAllDayCheckBox = (CheckBox) view.findViewById(R.id.is_all_day);
- mCalendarsSpinner = (Spinner) view.findViewById(R.id.calendars);
+ mViewList.add(mAllDayCheckBox);
mRepeatsSpinner = (Spinner) view.findViewById(R.id.repeats);
+ mViewList.add(mRepeatsSpinner);
mTransparencySpinner = (Spinner) view.findViewById(R.id.availability);
+ mViewList.add(mTransparencySpinner);
mVisibilitySpinner = (Spinner) view.findViewById(R.id.visibility);
+ mViewList.add(mVisibilitySpinner);
+
mResponseSpinner = (Spinner) view.findViewById(R.id.response_value);
- mRemindersSeparator = view.findViewById(R.id.reminders_separator);
mRemindersContainer = (LinearLayout) view.findViewById(R.id.reminder_items_container);
mSaveButton = (Button) view.findViewById(R.id.save);
@@ -761,7 +776,7 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
mDiscardButton = (Button) view.findViewById(R.id.discard);
mDiscardButton.setOnClickListener(this);
- mAddAttendeesButton = (ImageButton) view.findViewById(R.id.attendee_add);
+ mAddAttendeesButton = (ImageButton) view.findViewById(R.id.add_attendee_button);
mAddAttendeesListener = new AddAttendeeClickListener();
mAddAttendeesButton.setOnClickListener(mAddAttendeesListener);
@@ -824,7 +839,13 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
// If the user is allowed to change the attendees set up the view and
// validator
- if (model.mHasAttendeeData) {
+ if (!model.mHasAttendeeData) {
+ mView.findViewById(R.id.attendees_group).setVisibility(View.GONE);
+ } else if (!EditEventHelper.canModifyEvent(model)) {
+ mView.findViewById(R.id.add_attendees_label).setVisibility(View.GONE);
+ mView.findViewById(R.id.add_attendees_group).setVisibility(View.GONE);
+ mAddAttendeesButton.setVisibility(View.GONE);
+ } else {
String domain = "gmail.com";
if (!TextUtils.isEmpty(model.mOwnerAccount)) {
String ownerDomain = EditEventHelper.extractDomain(model.mOwnerAccount);
@@ -835,9 +856,7 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
mAddressAdapter = new EmailAddressAdapter(mActivity);
mEmailValidator = new Rfc822Validator(domain);
mAttendeesList = initMultiAutoCompleteTextView(R.id.attendees);
- } else {
- View attGroup = mView.findViewById(R.id.attendees_group);
- attGroup.setVisibility(View.GONE);
+ mViewList.add(mAttendeesList);
}
mAllDayCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@@ -893,10 +912,19 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
mTimezoneDialog.getListView().setAdapter(mTimezoneAdapter);
}
- mSaveButton.setOnClickListener(this);
- mDeleteButton.setOnClickListener(this);
- mSaveButton.setEnabled(true);
- mDeleteButton.setEnabled(true);
+ if (EditEventHelper.canRespond(model) || EditEventHelper.canModifyEvent(model)) {
+ mSaveButton.setOnClickListener(this);
+ mSaveButton.setEnabled(true);
+ } else {
+ mSaveButton.setEnabled(false);
+ }
+
+ if (EditEventHelper.canModifyCalendar(model)) {
+ mDeleteButton.setOnClickListener(this);
+ mDeleteButton.setEnabled(true);
+ } else {
+ mDeleteButton.setEnabled(false);
+ }
// Initialize the reminder values array.
Resources r = mActivity.getResources();
@@ -925,23 +953,37 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
mReminderValues, mReminderLabels, minute);
}
}
- updateRemindersVisibility(numReminders);
- // Setup the + Add Reminder Button
+ ImageButton reminderAddButton = (ImageButton) mView.findViewById(R.id.reminder_add);
View.OnClickListener addReminderOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
addReminder();
}
};
- ImageButton reminderRemoveButton = (ImageButton) mView.findViewById(R.id.reminder_add);
- reminderRemoveButton.setOnClickListener(addReminderOnClickListener);
+ reminderAddButton.setOnClickListener(addReminderOnClickListener);
+ updateRemindersVisibility(numReminders);
mTitleTextView.setText(model.mTitle);
+ if (model.mIsOrganizer || TextUtils.isEmpty(model.mOrganizer)
+ || model.mOrganizer.endsWith(GOOGLE_SECONDARY_CALENDAR)) {
+ mView.findViewById(R.id.organizer_label).setVisibility(View.GONE);
+ mView.findViewById(R.id.organizer).setVisibility(View.GONE);
+ } else {
+ ((TextView) mView.findViewById(R.id.organizer)).setText(model.mOrganizerDisplayName);
+ }
mLocationTextView.setText(model.mLocation);
mDescriptionTextView.setText(model.mDescription);
mTransparencySpinner.setSelection(model.mTransparency ? 1 : 0);
mVisibilitySpinner.setSelection(model.mVisibility);
mResponseSpinner.setSelection(findResponseIndexFor(model.mSelfAttendeeStatus));
+ View responseLabel = mView.findViewById(R.id.response_label);
+ if (EditEventHelper.canRespond(model)) {
+ responseLabel.setVisibility(View.VISIBLE);
+ mResponseSpinner.setVisibility(View.VISIBLE);
+ } else {
+ responseLabel.setVisibility(View.GONE);
+ mResponseSpinner.setVisibility(View.GONE);
+ }
if (model.mUri != null) {
// This is an existing event so hide the calendar spinner
@@ -956,6 +998,11 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
populateTimezone();
populateRepeats();
updateAttendees(model.mAttendeesList);
+ if (!EditEventHelper.canModifyEvent(mModel)) {
+ for (View v : mViewList) {
+ v.setEnabled(false);
+ }
+ }
mScrollView.setVisibility(View.VISIBLE);
mLoadingMessage.setVisibility(View.GONE);
}
@@ -1001,7 +1048,6 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
CalendarsAdapter adapter = new CalendarsAdapter(mActivity, cursor);
mCalendarsSpinner.setAdapter(adapter);
mCalendarsSpinner.setSelection(defaultCalendarPosition);
- mCalendarsCursorSet = true;
// Find user domain and set it to the validator.
// TODO: we may want to update this validator if the user actually picks
@@ -1072,6 +1118,7 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
return 0;
}
+ // FRAG_TODO convert this from listview to linearlayout
public void updateAttendees(HashMap<String, Attendee> attendeesList) {
if (mAttendeesAdapter == null) {
mAttendeesAdapter = new AttendeesAdapter(mActivity, mEmailValidator);
@@ -1084,10 +1131,8 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa
private void updateRemindersVisibility(int numReminders) {
if (numReminders == 0) {
- mRemindersSeparator.setVisibility(View.GONE);
mRemindersContainer.setVisibility(View.GONE);
} else {
- mRemindersSeparator.setVisibility(View.VISIBLE);
mRemindersContainer.setVisibility(View.VISIBLE);
}
}