Do not merge.
Revise NotePad application to use better practices such as
        - inflating menus from XML and supporting API Level 3 without the need
        for version qualifiers on resource directories.
        - to NOT include items in the options menu based on the 'selected' item
        (that's what a context menu is for).
        - include all drawables in the app, instead of using system resources.

        Add features:
        - the ability to edit the note title through the context menu
        - disable menu items in the editor based on menu groups
        - add a "save" button to the editor instead of assuming BACK functionality
        - and show the title of the current note in the activity title.
        - and probably others

Change-Id: Ib7ea41079f3b268f3be1f86febdb1caed98bdd8e
diff --git a/samples/NotePad/AndroidManifest.xml b/samples/NotePad/AndroidManifest.xml
index 04f4dbe..b87dfe3 100644
--- a/samples/NotePad/AndroidManifest.xml
+++ b/samples/NotePad/AndroidManifest.xml
@@ -20,16 +20,15 @@
      own application, the package name must be changed from "com.example.*"
      to come from a domain that you own or have control over. -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.notepad"
->
-    <application android:icon="@drawable/app_notes"
-        android:label="@string/app_name"
-    >
-        <provider android:name="NotePadProvider"
-            android:authorities="com.google.provider.NotePad"
-        />
+    package="com.example.android.notepad" >
 
-        <activity android:name="NotesList" android:label="@string/title_notes_list">
+    <application android:icon="@drawable/app_notes"
+        android:label="@string/app_name" >
+        <provider android:name="NotePadProvider"
+            android:authorities="com.example.notepad.provider.NotePad" />
+
+        <activity android:name="NotesList"
+            android:label="@string/title_notes_list">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -50,16 +49,13 @@
 
         <activity android:name="NoteEditor"
             android:theme="@android:style/Theme.Light"
-            android:label="@string/title_note"
-            android:screenOrientation="sensor"
-            android:configChanges="keyboardHidden|orientation"
-        >
+            android:configChanges="keyboardHidden|orientation">
             <!-- This filter says that we can view or edit the data of
                  a single note -->
             <intent-filter android:label="@string/resolve_edit">
                 <action android:name="android.intent.action.VIEW" />
                 <action android:name="android.intent.action.EDIT" />
-                <action android:name="com.android.notepad.action.EDIT_NOTE" />
+                <action android:name="com.android.notes.action.EDIT_NOTE" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
             </intent-filter>
@@ -77,6 +73,7 @@
         <activity android:name="TitleEditor"
             android:label="@string/title_edit_title"
             android:theme="@android:style/Theme.Dialog"
+            android:icon="@drawable/ic_menu_edit"
             android:windowSoftInputMode="stateVisible">
             <!-- This activity implements an alternative action that can be
                  performed on notes: editing their title.  It can be used as
@@ -110,6 +107,6 @@
 
     </application>
 
-    <uses-sdk android:targetSdkVersion="4" android:minSdkVersion="3"/>
+    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4"/>
 </manifest>
 
diff --git a/samples/NotePad/res/drawable-hdpi-v6/app_notes.png b/samples/NotePad/res/drawable-hdpi-v6/app_notes.png
deleted file mode 100644
index 3491823..0000000
--- a/samples/NotePad/res/drawable-hdpi-v6/app_notes.png
+++ /dev/null
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/app_notes.png b/samples/NotePad/res/drawable-hdpi/app_notes.png
old mode 100755
new mode 100644
index 258d3d1..3491823
--- a/samples/NotePad/res/drawable-hdpi/app_notes.png
+++ b/samples/NotePad/res/drawable-hdpi/app_notes.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_compose.png b/samples/NotePad/res/drawable-hdpi/ic_menu_compose.png
new file mode 100644
index 0000000..6ad379e
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_compose.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_delete.png b/samples/NotePad/res/drawable-hdpi/ic_menu_delete.png
new file mode 100644
index 0000000..2aed26a
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_delete.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_discard.png b/samples/NotePad/res/drawable-hdpi/ic_menu_discard.png
new file mode 100644
index 0000000..a54ea9d
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_discard.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_edit.png b/samples/NotePad/res/drawable-hdpi/ic_menu_edit.png
new file mode 100644
index 0000000..602dd10
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_edit.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_revert.png b/samples/NotePad/res/drawable-hdpi/ic_menu_revert.png
new file mode 100644
index 0000000..11860a4
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_revert.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi/ic_menu_save.png b/samples/NotePad/res/drawable-hdpi/ic_menu_save.png
new file mode 100644
index 0000000..fc26c5d
--- /dev/null
+++ b/samples/NotePad/res/drawable-hdpi/ic_menu_save.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-hdpi-v6/live_folder_notes.png b/samples/NotePad/res/drawable-hdpi/live_folder_notes.png
similarity index 100%
rename from samples/NotePad/res/drawable-hdpi-v6/live_folder_notes.png
rename to samples/NotePad/res/drawable-hdpi/live_folder_notes.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-ldpi-v6/app_notes.png b/samples/NotePad/res/drawable-ldpi/app_notes.png
similarity index 100%
rename from samples/NotePad/res/drawable-ldpi-v6/app_notes.png
rename to samples/NotePad/res/drawable-ldpi/app_notes.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-ldpi-v6/live_folder_notes.png b/samples/NotePad/res/drawable-ldpi/live_folder_notes.png
similarity index 100%
rename from samples/NotePad/res/drawable-ldpi-v6/live_folder_notes.png
rename to samples/NotePad/res/drawable-ldpi/live_folder_notes.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-mdpi/app_notes.png b/samples/NotePad/res/drawable-mdpi/app_notes.png
deleted file mode 100644
index 0479138..0000000
--- a/samples/NotePad/res/drawable-mdpi/app_notes.png
+++ /dev/null
Binary files differ
diff --git a/samples/NotePad/res/drawable-mdpi/live_folder_notes.png b/samples/NotePad/res/drawable-mdpi/live_folder_notes.png
deleted file mode 100644
index ac54a49..0000000
--- a/samples/NotePad/res/drawable-mdpi/live_folder_notes.png
+++ /dev/null
Binary files differ
diff --git a/samples/NotePad/res/drawable-mdpi-v6/app_notes.png b/samples/NotePad/res/drawable/app_notes.png
similarity index 100%
rename from samples/NotePad/res/drawable-mdpi-v6/app_notes.png
rename to samples/NotePad/res/drawable/app_notes.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_compose.png b/samples/NotePad/res/drawable/ic_menu_compose.png
new file mode 100644
index 0000000..1b4733e
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_compose.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_delete.png b/samples/NotePad/res/drawable/ic_menu_delete.png
new file mode 100755
index 0000000..7d95494
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_delete.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_discard.png b/samples/NotePad/res/drawable/ic_menu_discard.png
new file mode 100644
index 0000000..78222ea
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_discard.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_edit.png b/samples/NotePad/res/drawable/ic_menu_edit.png
new file mode 100755
index 0000000..41a9c2e
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_edit.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_revert.png b/samples/NotePad/res/drawable/ic_menu_revert.png
new file mode 100644
index 0000000..e7e04f5
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_revert.png
Binary files differ
diff --git a/samples/NotePad/res/drawable/ic_menu_save.png b/samples/NotePad/res/drawable/ic_menu_save.png
new file mode 100644
index 0000000..36d50b3
--- /dev/null
+++ b/samples/NotePad/res/drawable/ic_menu_save.png
Binary files differ
diff --git a/samples/NotePad/res/drawable-mdpi-v6/live_folder_notes.png b/samples/NotePad/res/drawable/live_folder_notes.png
similarity index 100%
rename from samples/NotePad/res/drawable-mdpi-v6/live_folder_notes.png
rename to samples/NotePad/res/drawable/live_folder_notes.png
Binary files differ
diff --git a/samples/NotePad/res/layout/note_editor.xml b/samples/NotePad/res/layout/note_editor.xml
index d7da99e..f142c71 100644
--- a/samples/NotePad/res/layout/note_editor.xml
+++ b/samples/NotePad/res/layout/note_editor.xml
@@ -13,17 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <view xmlns:android="http://schemas.android.com/apk/res/android"
     class="com.example.android.notepad.NoteEditor$LinedEditText"
     android:id="@+id/note"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
     android:background="@android:color/transparent"
-    android:padding="5dip"
+    android:padding="5dp"
     android:scrollbars="vertical"
     android:fadingEdge="vertical"
     android:gravity="top"
     android:textSize="22sp"
-    android:capitalize="sentences"
-/>
+    android:capitalize="sentences" />
diff --git a/samples/NotePad/res/layout/noteslist_item.xml b/samples/NotePad/res/layout/noteslist_item.xml
index e11c5ee..b167734 100644
--- a/samples/NotePad/res/layout/noteslist_item.xml
+++ b/samples/NotePad/res/layout/noteslist_item.xml
@@ -16,7 +16,7 @@
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@android:id/text1"
-    android:layout_width="match_parent"
+    android:layout_width="fill_parent"
     android:layout_height="?android:attr/listPreferredItemHeight"
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:gravity="center_vertical"
diff --git a/samples/NotePad/res/menu/editor_options_menu.xml b/samples/NotePad/res/menu/editor_options_menu.xml
new file mode 100644
index 0000000..b2d14ac
--- /dev/null
+++ b/samples/NotePad/res/menu/editor_options_menu.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_save"
+          android:icon="@drawable/ic_menu_save"
+          android:alphabeticShortcut='s'
+          android:title="@string/menu_save" />
+    <group android:id="@+id/menu_group_edit">
+        <item android:id="@+id/menu_revert"
+              android:icon="@drawable/ic_menu_revert"
+              android:title="@string/menu_revert" />
+        <item android:id="@+id/menu_delete"
+              android:icon="@drawable/ic_menu_delete"
+              android:title="@string/menu_delete" />
+    </group>
+    <group android:id="@+id/menu_group_insert">
+        <item android:id="@+id/menu_discard"
+              android:icon="@drawable/ic_menu_discard"
+              android:title="@string/menu_discard" />
+    </group>
+</menu>
\ No newline at end of file
diff --git a/samples/NotePad/res/menu/list_context_menu.xml b/samples/NotePad/res/menu/list_context_menu.xml
new file mode 100644
index 0000000..acc8edd
--- /dev/null
+++ b/samples/NotePad/res/menu/list_context_menu.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/context_open"
+          android:title="@string/menu_open" />
+    <item android:id="@+id/context_delete"
+          android:title="@string/menu_delete" />
+</menu>
\ No newline at end of file
diff --git a/samples/NotePad/res/menu/list_options_menu.xml b/samples/NotePad/res/menu/list_options_menu.xml
new file mode 100644
index 0000000..9754554
--- /dev/null
+++ b/samples/NotePad/res/menu/list_options_menu.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--  This is our one standard application action (creating a new note). -->
+    <item android:id="@+id/menu_add"
+          android:icon="@drawable/ic_menu_compose"
+          android:alphabeticShortcut='a'
+          android:title="@string/menu_add" />
+</menu>
\ No newline at end of file
diff --git a/samples/NotePad/res/values/strings.xml b/samples/NotePad/res/values/strings.xml
index 168db92..4100652 100644
--- a/samples/NotePad/res/values/strings.xml
+++ b/samples/NotePad/res/values/strings.xml
@@ -15,25 +15,28 @@
 -->
 
 <resources>
-    <string name="menu_delete">Delete</string>
-    <string name="menu_insert">Add note</string>
-    <string name="menu_revert">Revert</string>
-    <string name="menu_discard">Discard</string>
-
-    <string name="resolve_edit">Edit note</string>
-    <string name="resolve_title">Edit title</string>  
-
+    <string name="app_name">NotePad</string>
+    <string name="live_folder_name">Notes</string>
+    
+    <string name="title_edit_title">Note title:</string>
     <string name="title_create">Create note</string>
-    <string name="title_edit">Edit note</string>
-	<string name="title_notes_list">Note pad</string>   
-	<string name="title_note">Note</string>  
-	<string name="title_edit_title">Note title:</string>  
-	
-	<string name="app_name">Note Pad</string>  
-	<string name="live_folder_name">Notes</string>
-	
-	<string name="button_ok">OK</string>  
-	
-	<string name="error_title">Error</string>
-	<string name="error_message">Error loading note</string>
-</resources>
+    <string name="title_edit">Edit: \"%1$s\"</string>
+    <string name="title_notes_list">Notes</string>
+    
+    <string name="menu_add">Add note</string>
+    <string name="menu_save">Save</string>
+    <string name="menu_delete">Delete</string>
+    <string name="menu_open">Open</string>
+    <string name="menu_revert">Revert changes</string>
+    <string name="menu_discard">Discard</string>
+    
+    <string name="button_ok">OK</string>  
+    <string name="text_title">Title:</string>
+    
+    <string name="resolve_edit">Edit note</string>
+    <string name="resolve_title">Edit title</string>
+    
+    <string name="error_title">Error</string>
+    <string name="error_message">Error loading note</string>
+    <string name="nothing_to_save">There is nothing to save</string>
+</resources>
\ No newline at end of file
diff --git a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
index e45efd8..66f4ce6 100644
--- a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
+++ b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
@@ -16,13 +16,12 @@
 
 package com.example.android.notepad;
 
-import com.example.android.notepad.NotePad.Notes;
-
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -32,8 +31,12 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.widget.EditText;
+import android.widget.Toast;
+
+import com.example.android.notepad.NotePad.NoteColumns;
 
 /**
  * A generic activity for editing a note in a database.  This can be used
@@ -41,32 +44,29 @@
  * {@link Intent#ACTION_EDIT}, or create a new note {@link Intent#ACTION_INSERT}.  
  */
 public class NoteEditor extends Activity {
-    private static final String TAG = "Notes";
+    private static final String TAG = "NoteEditor";
 
     /**
      * Standard projection for the interesting columns of a normal note.
      */
     private static final String[] PROJECTION = new String[] {
-            Notes._ID, // 0
-            Notes.NOTE, // 1
+        NoteColumns._ID, // 0
+        NoteColumns.NOTE, // 1
+        NoteColumns.TITLE, // 2
     };
     /** The index of the note column */
     private static final int COLUMN_INDEX_NOTE = 1;
+    /** The index of the title column */
+    private static final int COLUMN_INDEX_TITLE = 2;
     
     // This is our state data that is stored when freezing.
     private static final String ORIGINAL_CONTENT = "origContent";
 
-    // Identifiers for our menu items.
-    private static final int REVERT_ID = Menu.FIRST;
-    private static final int DISCARD_ID = Menu.FIRST + 1;
-    private static final int DELETE_ID = Menu.FIRST + 2;
-
     // The different distinct states the activity can be run in.
     private static final int STATE_EDIT = 0;
     private static final int STATE_INSERT = 1;
 
     private int mState;
-    private boolean mNoteOnly = false;
     private Uri mUri;
     private Cursor mCursor;
     private EditText mText;
@@ -112,7 +112,6 @@
         final Intent intent = getIntent();
 
         // Do some setup based on the action being performed.
-
         final String action = intent.getAction();
         if (Intent.ACTION_EDIT.equals(action)) {
             // Requested to edit: set that state, and the data being edited.
@@ -163,16 +162,21 @@
     @Override
     protected void onResume() {
         super.onResume();
-
         // If we didn't have any trouble retrieving the data, it is now
         // time to get at the stuff.
         if (mCursor != null) {
+            // Requery in case something changed while paused (such as the title)
+            mCursor.requery();
             // Make sure we are at the one and only row in the cursor.
             mCursor.moveToFirst();
 
             // Modify our overall title depending on the mode we are running in.
             if (mState == STATE_EDIT) {
-                setTitle(getText(R.string.title_edit));
+                // Set the title of the Activity to include the note title
+                String title = mCursor.getString(COLUMN_INDEX_TITLE);
+                Resources res = getResources();
+                String text = String.format(res.getString(R.string.title_edit), title);
+                setTitle(text);
             } else if (mState == STATE_INSERT) {
                 setTitle(getText(R.string.title_create));
             }
@@ -206,109 +210,129 @@
     @Override
     protected void onPause() {
         super.onPause();
+        // The user is going somewhere, so make sure changes are saved
 
-        // The user is going somewhere else, so make sure their current
-        // changes are safely saved away in the provider.  We don't need
-        // to do this if only editing.
-        if (mCursor != null) {
-            String text = mText.getText().toString();
-            int length = text.length();
+        String text = mText.getText().toString();
+        int length = text.length();
 
-            // If this activity is finished, and there is no text, then we
-            // do something a little special: simply delete the note entry.
-            // Note that we do this both for editing and inserting...  it
-            // would be reasonable to only do it when inserting.
-            if (isFinishing() && (length == 0) && !mNoteOnly) {
-                setResult(RESULT_CANCELED);
-                deleteNote();
-
-            // Get out updates into the provider.
-            } else {
-                ContentValues values = new ContentValues();
-
-                // This stuff is only done when working with a full-fledged note.
-                if (!mNoteOnly) {
-                    // Bump the modification time to now.
-                    values.put(Notes.MODIFIED_DATE, System.currentTimeMillis());
-
-                    // If we are creating a new note, then we want to also create
-                    // an initial title for it.
-                    if (mState == STATE_INSERT) {
-                        String title = text.substring(0, Math.min(30, length));
-                        if (length > 30) {
-                            int lastSpace = title.lastIndexOf(' ');
-                            if (lastSpace > 0) {
-                                title = title.substring(0, lastSpace);
-                            }
-                        }
-                        values.put(Notes.TITLE, title);
-                    }
-                }
-
-                // Write our text back into the provider.
-                values.put(Notes.NOTE, text);
-
-                // Commit all of our changes to persistent storage. When the update completes
-                // the content provider will notify the cursor of the change, which will
-                // cause the UI to be updated.
-                getContentResolver().update(mUri, values, null, null);
-            }
+        // If this activity is finished, and there is no text, then we
+        // simply delete the note entry.
+        // Note that we do this both for editing and inserting...  it
+        // would be reasonable to only do it when inserting.
+        if (isFinishing() && (length == 0) && mCursor != null) {
+            setResult(RESULT_CANCELED);
+            deleteNote();
+        } else {
+            saveNote();
         }
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
+        // Inflate menu from XML resource
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.editor_options_menu, menu);
 
-        // Build the menus that are shown when editing.
-        if (mState == STATE_EDIT) {
-            menu.add(0, REVERT_ID, 0, R.string.menu_revert)
-                    .setShortcut('0', 'r')
-                    .setIcon(android.R.drawable.ic_menu_revert);
-            if (!mNoteOnly) {
-                menu.add(0, DELETE_ID, 0, R.string.menu_delete)
-                        .setShortcut('1', 'd')
-                        .setIcon(android.R.drawable.ic_menu_delete);
-            }
-
-        // Build the menus that are shown when inserting.
-        } else {
-            menu.add(0, DISCARD_ID, 0, R.string.menu_discard)
-                    .setShortcut('0', 'd')
-                    .setIcon(android.R.drawable.ic_menu_delete);
-        }
-
-        // If we are working on a full note, then append to the
+        // Append to the
         // menu items for any other activities that can do stuff with it
         // as well.  This does a query on the system for any activities that
         // implement the ALTERNATIVE_ACTION for our data, adding a menu item
         // for each one that is found.
-        if (!mNoteOnly) {
-            Intent intent = new Intent(null, getIntent().getData());
-            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
-            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
-                    new ComponentName(this, NoteEditor.class), null, intent, 0, null);
-        }
+        Intent intent = new Intent(null, getIntent().getData());
+        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+                new ComponentName(this, NoteEditor.class), null, intent, 0, null);
 
-        return true;
+        return super.onCreateOptionsMenu(menu);
+    }
+    
+    
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        if (mState == STATE_EDIT) {
+            menu.setGroupVisible(R.id.menu_group_edit, true);
+            menu.setGroupVisible(R.id.menu_group_insert, false);
+            
+            // Check if note has changed and enable/disable the revert option
+            String savedNote = mCursor.getString(COLUMN_INDEX_NOTE);
+            String currentNote = mText.getText().toString();
+            if (savedNote.equals(currentNote)) {
+                menu.findItem(R.id.menu_revert).setEnabled(false);
+            } else {
+                menu.findItem(R.id.menu_revert).setEnabled(true);
+            }
+        } else {
+            menu.setGroupVisible(R.id.menu_group_edit, false);
+            menu.setGroupVisible(R.id.menu_group_insert, true);
+        }
+        return super.onPrepareOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         // Handle all of the possible menu actions.
         switch (item.getItemId()) {
-        case DELETE_ID:
+        case R.id.menu_save:
+            saveNote();
+            finish();
+            break;
+        case R.id.menu_delete:
             deleteNote();
             finish();
             break;
-        case DISCARD_ID:
-            cancelNote();
-            break;
-        case REVERT_ID:
+        case R.id.menu_revert:
+        case R.id.menu_discard:
             cancelNote();
             break;
         }
         return super.onOptionsItemSelected(item);
+        
+    }
+    
+    private final void saveNote() {
+        // Make sure their current
+        // changes are safely saved away in the provider.  We don't need
+        // to do this if only editing.
+        if (mCursor != null) {
+            // Get out updates into the provider.
+            ContentValues values = new ContentValues();
+
+            // Bump the modification time to now.
+            values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
+
+            String text = mText.getText().toString();
+            int length = text.length();
+            // If we are creating a new note, then we want to also create
+            // an initial title for it.
+            if (mState == STATE_INSERT) {
+                if (length == 0) {
+                    Toast.makeText(this, R.string.nothing_to_save, Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                String title = text.substring(0, Math.min(30, length));
+                if (length > 30) {
+                    int lastSpace = title.lastIndexOf(' ');
+                    if (lastSpace > 0) {
+                        title = title.substring(0, lastSpace);
+                    }
+                }
+                values.put(NoteColumns.TITLE, title);
+            }
+
+            // Write our text back into the provider.
+            values.put(NoteColumns.NOTE, text);
+
+            // Commit all of our changes to persistent storage. When the update completes
+            // the content provider will notify the cursor of the change, which will
+            // cause the UI to be updated.
+            try {
+                getContentResolver().update(mUri, values, null, null);
+            } catch (NullPointerException e) {
+                Log.e(TAG, e.getMessage());
+            }
+            
+        }
     }
 
     /**
@@ -322,7 +346,7 @@
                 mCursor.close();
                 mCursor = null;
                 ContentValues values = new ContentValues();
-                values.put(Notes.NOTE, mOriginalContent);
+                values.put(NoteColumns.NOTE, mOriginalContent);
                 getContentResolver().update(mUri, values, null, null);
             } else if (mState == STATE_INSERT) {
                 // We inserted an empty note, make sure to delete it
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePad.java b/samples/NotePad/src/com/example/android/notepad/NotePad.java
index 25be23e..09087db 100644
--- a/samples/NotePad/src/com/example/android/notepad/NotePad.java
+++ b/samples/NotePad/src/com/example/android/notepad/NotePad.java
@@ -23,7 +23,7 @@
  * Convenience definitions for NotePadProvider
  */
 public final class NotePad {
-    public static final String AUTHORITY = "com.google.provider.NotePad";
+    public static final String AUTHORITY = "com.example.notepad.provider.NotePad";
 
     // This class cannot be instantiated
     private NotePad() {}
@@ -31,9 +31,9 @@
     /**
      * Notes table
      */
-    public static final class Notes implements BaseColumns {
+    public static final class NoteColumns implements BaseColumns {
         // This class cannot be instantiated
-        private Notes() {}
+        private NoteColumns() {}
 
         /**
          * The content:// style URL for this table
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
index 58cdc8f..5c349c5 100644
--- a/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
+++ b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
@@ -16,7 +16,7 @@
 
 package com.example.android.notepad;
 
-import com.example.android.notepad.NotePad.Notes;
+import com.example.android.notepad.NotePad.NoteColumns;
 
 import android.content.ContentProvider;
 import android.content.ContentUris;
@@ -44,7 +44,7 @@
 
     private static final String TAG = "NotePadProvider";
 
-    private static final String DATABASE_NAME = "note_pad.db";
+    private static final String DATABASE_NAME = "notepad.db";
     private static final int DATABASE_VERSION = 2;
     private static final String NOTES_TABLE_NAME = "notes";
 
@@ -69,11 +69,11 @@
         @Override
         public void onCreate(SQLiteDatabase db) {
             db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " ("
-                    + Notes._ID + " INTEGER PRIMARY KEY,"
-                    + Notes.TITLE + " TEXT,"
-                    + Notes.NOTE + " TEXT,"
-                    + Notes.CREATED_DATE + " INTEGER,"
-                    + Notes.MODIFIED_DATE + " INTEGER"
+                    + NoteColumns._ID + " INTEGER PRIMARY KEY,"
+                    + NoteColumns.TITLE + " TEXT,"
+                    + NoteColumns.NOTE + " TEXT,"
+                    + NoteColumns.CREATED_DATE + " INTEGER,"
+                    + NoteColumns.MODIFIED_DATE + " INTEGER"
                     + ");");
         }
 
@@ -107,7 +107,7 @@
 
         case NOTE_ID:
             qb.setProjectionMap(sNotesProjectionMap);
-            qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));
+            qb.appendWhere(NoteColumns._ID + "=" + uri.getPathSegments().get(1));
             break;
 
         case LIVE_FOLDER_NOTES:
@@ -121,7 +121,7 @@
         // If no sort order is specified use the default
         String orderBy;
         if (TextUtils.isEmpty(sortOrder)) {
-            orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
+            orderBy = NoteColumns.DEFAULT_SORT_ORDER;
         } else {
             orderBy = sortOrder;
         }
@@ -140,10 +140,10 @@
         switch (sUriMatcher.match(uri)) {
         case NOTES:
         case LIVE_FOLDER_NOTES:
-            return Notes.CONTENT_TYPE;
+            return NoteColumns.CONTENT_TYPE;
 
         case NOTE_ID:
-            return Notes.CONTENT_ITEM_TYPE;
+            return NoteColumns.CONTENT_ITEM_TYPE;
 
         default:
             throw new IllegalArgumentException("Unknown URI " + uri);
@@ -167,27 +167,27 @@
         Long now = Long.valueOf(System.currentTimeMillis());
 
         // Make sure that the fields are all set
-        if (values.containsKey(NotePad.Notes.CREATED_DATE) == false) {
-            values.put(NotePad.Notes.CREATED_DATE, now);
+        if (values.containsKey(NoteColumns.CREATED_DATE) == false) {
+            values.put(NoteColumns.CREATED_DATE, now);
         }
 
-        if (values.containsKey(NotePad.Notes.MODIFIED_DATE) == false) {
-            values.put(NotePad.Notes.MODIFIED_DATE, now);
+        if (values.containsKey(NoteColumns.MODIFIED_DATE) == false) {
+            values.put(NoteColumns.MODIFIED_DATE, now);
         }
 
-        if (values.containsKey(NotePad.Notes.TITLE) == false) {
+        if (values.containsKey(NoteColumns.TITLE) == false) {
             Resources r = Resources.getSystem();
-            values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));
+            values.put(NoteColumns.TITLE, r.getString(android.R.string.untitled));
         }
 
-        if (values.containsKey(NotePad.Notes.NOTE) == false) {
-            values.put(NotePad.Notes.NOTE, "");
+        if (values.containsKey(NoteColumns.NOTE) == false) {
+            values.put(NoteColumns.NOTE, "");
         }
 
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);
+        long rowId = db.insert(NOTES_TABLE_NAME, NoteColumns.NOTE, values);
         if (rowId > 0) {
-            Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
+            Uri noteUri = ContentUris.withAppendedId(NoteColumns.CONTENT_URI, rowId);
             getContext().getContentResolver().notifyChange(noteUri, null);
             return noteUri;
         }
@@ -206,7 +206,7 @@
 
         case NOTE_ID:
             String noteId = uri.getPathSegments().get(1);
-            count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId
+            count = db.delete(NOTES_TABLE_NAME, NoteColumns._ID + "=" + noteId
                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
             break;
 
@@ -229,7 +229,7 @@
 
         case NOTE_ID:
             String noteId = uri.getPathSegments().get(1);
-            count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId
+            count = db.update(NOTES_TABLE_NAME, values, NoteColumns._ID + "=" + noteId
                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
             break;
 
@@ -248,17 +248,17 @@
         sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES);
 
         sNotesProjectionMap = new HashMap<String, String>();
-        sNotesProjectionMap.put(Notes._ID, Notes._ID);
-        sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
-        sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
-        sNotesProjectionMap.put(Notes.CREATED_DATE, Notes.CREATED_DATE);
-        sNotesProjectionMap.put(Notes.MODIFIED_DATE, Notes.MODIFIED_DATE);
+        sNotesProjectionMap.put(NoteColumns._ID, NoteColumns._ID);
+        sNotesProjectionMap.put(NoteColumns.TITLE, NoteColumns.TITLE);
+        sNotesProjectionMap.put(NoteColumns.NOTE, NoteColumns.NOTE);
+        sNotesProjectionMap.put(NoteColumns.CREATED_DATE, NoteColumns.CREATED_DATE);
+        sNotesProjectionMap.put(NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE);
 
         // Support for Live Folders.
         sLiveFolderProjectionMap = new HashMap<String, String>();
-        sLiveFolderProjectionMap.put(LiveFolders._ID, Notes._ID + " AS " +
+        sLiveFolderProjectionMap.put(LiveFolders._ID, NoteColumns._ID + " AS " +
                 LiveFolders._ID);
-        sLiveFolderProjectionMap.put(LiveFolders.NAME, Notes.TITLE + " AS " +
+        sLiveFolderProjectionMap.put(LiveFolders.NAME, NoteColumns.TITLE + " AS " +
                 LiveFolders.NAME);
         // Add more columns here for more robust Live Folders.
     }
diff --git a/samples/NotePad/src/com/example/android/notepad/NotesList.java b/samples/NotePad/src/com/example/android/notepad/NotesList.java
index ceaaa3c..ec80902 100644
--- a/samples/NotePad/src/com/example/android/notepad/NotesList.java
+++ b/samples/NotePad/src/com/example/android/notepad/NotesList.java
@@ -16,8 +16,6 @@
 
 package com.example.android.notepad;
 
-import com.example.android.notepad.NotePad.Notes;
-
 import android.app.ListActivity;
 import android.content.ComponentName;
 import android.content.ContentUris;
@@ -28,6 +26,7 @@
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -35,24 +34,22 @@
 import android.widget.ListView;
 import android.widget.SimpleCursorAdapter;
 
+import com.example.android.notepad.NotePad.NoteColumns;
+
 /**
  * Displays a list of notes. Will display notes from the {@link Uri}
  * provided in the intent if there is one, otherwise defaults to displaying the
- * contents of the {@link NotePadProvider}
+ * contents of the {@link NoteProvider}
  */
 public class NotesList extends ListActivity {
     private static final String TAG = "NotesList";
 
-    // Menu item ids
-    public static final int MENU_ITEM_DELETE = Menu.FIRST;
-    public static final int MENU_ITEM_INSERT = Menu.FIRST + 1;
-
     /**
      * The columns we are interested in from the database
      */
     private static final String[] PROJECTION = new String[] {
-            Notes._ID, // 0
-            Notes.TITLE, // 1
+        NoteColumns._ID, // 0
+        NoteColumns.TITLE, // 1
     };
 
     /** The index of the title column */
@@ -68,7 +65,7 @@
         // as a MAIN activity), then use our default content provider.
         Intent intent = getIntent();
         if (intent.getData() == null) {
-            intent.setData(Notes.CONTENT_URI);
+            intent.setData(NoteColumns.CONTENT_URI);
         }
 
         // Inform the list we provide context menus for items
@@ -77,24 +74,20 @@
         // Perform a managed query. The Activity will handle closing and requerying the cursor
         // when needed.
         Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null,
-                Notes.DEFAULT_SORT_ORDER);
+                                        NoteColumns.DEFAULT_SORT_ORDER);
 
         // Used to map notes entries from the database to views
         SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
-                new String[] { Notes.TITLE }, new int[] { android.R.id.text1 });
+                new String[] { NoteColumns.TITLE }, new int[] { android.R.id.text1 });
         setListAdapter(adapter);
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-
-        // This is our one standard application action -- inserting a
-        // new note into the list.
-        menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
-                .setShortcut('3', 'a')
-                .setIcon(android.R.drawable.ic_menu_add);
-
+        // Inflate menu from XML resource
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.list_options_menu, menu);
+        
         // Generate any additional actions that can be performed on the
         // overall list.  In a normal install, there are no additional
         // actions found here, but this allows other applications to extend
@@ -104,54 +97,19 @@
         menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
                 new ComponentName(this, NotesList.class), null, intent, 0, null);
 
-        return true;
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        super.onPrepareOptionsMenu(menu);
-        final boolean haveItems = getListAdapter().getCount() > 0;
-
-        // If there are any notes in the list (which implies that one of
-        // them is selected), then we need to generate the actions that
-        // can be performed on the current selection.  This will be a combination
-        // of our own specific actions along with any extensions that can be
-        // found.
-        if (haveItems) {
-            // This is the selected item.
-            Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());
-
-            // Build menu...  always starts with the EDIT action...
-            Intent[] specifics = new Intent[1];
-            specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
-            MenuItem[] items = new MenuItem[1];
-
-            // ... is followed by whatever other actions are available...
-            Intent intent = new Intent(null, uri);
-            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
-            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
-                    items);
-
-            // Give a shortcut to the edit action.
-            if (items[0] != null) {
-                items[0].setShortcut('1', 'e');
-            }
-        } else {
-            menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
-        }
-
-        return true;
+        return super.onCreateOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
-        case MENU_ITEM_INSERT:
+        case R.id.menu_add:
             // Launch activity to insert a new item
             startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
             return true;
+        default:
+            return super.onOptionsItemSelected(item);
         }
-        return super.onOptionsItemSelected(item);
     }
 
     @Override
@@ -170,11 +128,23 @@
             return;
         }
 
-        // Setup the menu header
+        // Inflate menu from XML resource
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.list_context_menu, menu);
+        
+        // Set the context menu header
         menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
-
-        // Add a menu item to delete the note
-        menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete);
+        
+        // Append to the
+        // menu items for any other activities that can do stuff with it
+        // as well.  This does a query on the system for any activities that
+        // implement the ALTERNATIVE_ACTION for our data, adding a menu item
+        // for each one that is found.
+        Intent intent = new Intent(null, Uri.withAppendedPath(getIntent().getData(), 
+                                        Integer.toString((int) info.id) ));
+        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+                new ComponentName(this, NotesList.class), null, intent, 0, null);
     }
         
     @Override
@@ -186,30 +156,35 @@
             Log.e(TAG, "bad menuInfo", e);
             return false;
         }
+        
+        Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
 
         switch (item.getItemId()) {
-            case MENU_ITEM_DELETE: {
-                // Delete the note that the context menu is for
-                Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
-                getContentResolver().delete(noteUri, null, null);
-                return true;
-            }
+        case R.id.context_open:
+            // Launch activity to view/edit the currently selected item
+            startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
+            return true;
+        case R.id.context_delete:
+            // Delete the note that the context menu is for
+            getContentResolver().delete(noteUri, null, null);
+            return true;
+        default:
+            return super.onContextItemSelected(item);
         }
-        return false;
     }
 
     @Override
     protected void onListItemClick(ListView l, View v, int position, long id) {
-        Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);
+        Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), id);
         
         String action = getIntent().getAction();
         if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {
             // The caller is waiting for us to return a note selected by
             // the user.  The have clicked on one, so return it now.
-            setResult(RESULT_OK, new Intent().setData(uri));
+            setResult(RESULT_OK, new Intent().setData(noteUri));
         } else {
             // Launch activity to view/edit the currently selected item
-            startActivity(new Intent(Intent.ACTION_EDIT, uri));
+            startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
         }
     }
 }
diff --git a/samples/NotePad/src/com/example/android/notepad/TitleEditor.java b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
index 50d38e5..fe232ed 100644
--- a/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
+++ b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
@@ -16,8 +16,6 @@
 
 package com.example.android.notepad;
 
-import com.example.android.notepad.NotePad.Notes;
-
 import android.app.Activity;
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -27,6 +25,8 @@
 import android.widget.Button;
 import android.widget.EditText;
 
+import com.example.android.notepad.NotePad.NoteColumns;
+
 /**
  * An activity that will edit the title of a note. Displays a floating
  * window with a text field.
@@ -42,8 +42,8 @@
      * An array of the columns we are interested in.
      */
     private static final String[] PROJECTION = new String[] {
-            NotePad.Notes._ID, // 0
-            NotePad.Notes.TITLE, // 1
+        NoteColumns._ID, // 0
+        NoteColumns.TITLE, // 1
     };
     /** Index of the title column */
     private static final int COLUMN_INDEX_TITLE = 1;
@@ -102,7 +102,7 @@
         if (mCursor != null) {
             // Write the title back to the note 
             ContentValues values = new ContentValues();
-            values.put(Notes.TITLE, mText.getText().toString());
+            values.put(NoteColumns.TITLE, mText.getText().toString());
             getContentResolver().update(mUri, values, null, null);
         }
     }
diff --git a/samples/NotePad/src/com/google/provider/NotePad.java b/samples/NotePad/src/com/google/provider/NotePad.java
deleted file mode 100644
index f8de69b..0000000
--- a/samples/NotePad/src/com/google/provider/NotePad.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.provider;
-
-import android.net.Uri;
-import android.provider.BaseColumns;
-
-/**
- * Convenience definitions for NotePadProvider
- */
-public final class NotePad {
-    /**
-     * Notes table
-     */
-    public static final class Notes implements BaseColumns {
-        /**
-         * The content:// style URL for this table
-         */
-        public static final Uri CONTENT_URI
-                = Uri.parse("content://com.google.provider.NotePad/notes");
-
-        /**
-         * The default sort order for this table
-         */
-        public static final String DEFAULT_SORT_ORDER = "modified DESC";
-
-        /**
-         * The title of the note
-         * <P>Type: TEXT</P>
-         */
-        public static final String TITLE = "title";
-
-        /**
-         * The note itself
-         * <P>Type: TEXT</P>
-         */
-        public static final String NOTE = "note";
-
-        /**
-         * The timestamp for when the note was created
-         * <P>Type: INTEGER (long)</P>
-         */
-        public static final String CREATED_DATE = "created";
-
-        /**
-         * The timestamp for when the note was last modified
-         * <P>Type: INTEGER (long)</P>
-         */
-        public static final String MODIFIED_DATE = "modified";
-    }
-}