Merge "Make background media saving a service" into gb-ub-photos-bryce
diff --git a/res/drawable/filtershow_color_picker_circle.xml b/res/drawable/filtershow_color_picker_circle.xml
new file mode 100644
index 0000000..4444e0f
--- /dev/null
+++ b/res/drawable/filtershow_color_picker_circle.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval" >
+    <size android:width="20dp" android:height="20dp"/>
+    <corners
+        android:radius="10dp" />
+    <solid android:color="@color/red"/>
+</shape>
+
diff --git a/res/drawable/filtershow_color_picker_roundrect.xml b/res/drawable/filtershow_color_picker_roundrect.xml
new file mode 100644
index 0000000..89add5e
--- /dev/null
+++ b/res/drawable/filtershow_color_picker_roundrect.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <size android:width="20dp" android:height="20dp"/>
+    <corners android:radius="10dp" />
+    <solid android:color="@color/red"/>
+
+</shape>
+
diff --git a/res/layout/filtershow_color_gird.xml b/res/layout/filtershow_color_gird.xml
new file mode 100644
index 0000000..2dbbc5f
--- /dev/null
+++ b/res/layout/filtershow_color_gird.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/textView1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TableLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <TableRow
+            android:id="@+id/tableRow1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <Button
+                android:id="@+id/cp_grid_button01"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button2"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button03"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button04"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button05"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <Button
+                android:id="@+id/Button06"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button07"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button08"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button09"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button10"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow3"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <Button
+                android:id="@+id/Button11"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button12"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button13"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button14"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button15"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow4"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <Button
+                android:id="@+id/Button16"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button17"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button18"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button19"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+
+            <Button
+                android:id="@+id/button20"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/filtershow_color_picker_circle" />
+        </TableRow>
+    </TableLayout>
+
+    <Button
+        android:id="@+id/filtershow_cp_custom"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/color_pick_select" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_color_picker.xml b/res/layout/filtershow_color_picker.xml
new file mode 100644
index 0000000..fc49729
--- /dev/null
+++ b/res/layout/filtershow_color_picker.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/RelativeLayout1"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/default_background"
+    tools:context=".ColorPickerActivity" >
+
+    <com.android.gallery3d.filtershow.colorpicker.ColorRectView
+        android:id="@+id/colorRectView"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
+        android:layout_marginRight="1dp"
+        android:layout_above="@+id/colorOpacityView"
+        android:layout_toLeftOf="@+id/colorValueView" />
+
+    <com.android.gallery3d.filtershow.colorpicker.ColorValueView
+        android:id="@+id/colorValueView"
+               android:layout_width="90dp"
+        android:layout_height="fill_parent"
+        android:layout_alignParentRight = "true"
+        android:layout_above="@+id/colorOpacityView"  />
+
+    <com.android.gallery3d.filtershow.colorpicker.ColorOpacityView
+        android:id="@+id/colorOpacityView"
+       android:layout_width="match_parent"
+        android:layout_height="90dp"
+         android:layout_above="@+id/btnSelect" />
+
+    <Button
+        android:id="@+id/btnSelect"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/color_pick_select"
+        android:layout_alignParentBottom = "true"
+        />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_cp_custom_title.xml b/res/layout/filtershow_cp_custom_title.xml
new file mode 100644
index 0000000..cef8b6c
--- /dev/null
+++ b/res/layout/filtershow_cp_custom_title.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/customTitle"
+    android:text="@string/color_pick_title"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:layout_marginLeft="20dp"
+    android:layout_marginRight="20dp" >
+</TextView>
\ No newline at end of file
diff --git a/res/layout/filtershow_draw_button.xml b/res/layout/filtershow_draw_button.xml
new file mode 100644
index 0000000..dba8100
--- /dev/null
+++ b/res/layout/filtershow_draw_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<com.android.gallery3d.filtershow.ui.FramedTextButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/drawUtilityButton"
+    android:layout_width="84dip"
+    android:layout_height="84dip"
+    android:layout_gravity="center_vertical|left"
+    android:background="@drawable/filtershow_button_background"
+    android:scaleType="centerInside"
+    android:visibility="gone"
+    android:text="@string/draw_style" />
diff --git a/res/layout/filtershow_draw_size.xml b/res/layout/filtershow_draw_size.xml
new file mode 100644
index 0000000..068493e
--- /dev/null
+++ b/res/layout/filtershow_draw_size.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:dividerPadding="20dp"
+    android:gravity="center_horizontal"
+    android:orientation="vertical" >
+
+    <SeekBar
+        android:id="@+id/sizeSeekBar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <Button
+        android:id="@+id/sizeAcceptButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/draw_size_accept" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_draw.xml b/res/menu/filtershow_menu_draw.xml
new file mode 100644
index 0000000..be6dc70
--- /dev/null
+++ b/res/menu/filtershow_menu_draw.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <group android:id="@+id/curves_popupmenu" >
+        <item
+            android:id="@+id/draw_menu_style_line"
+            android:title="@string/draw_style_line" />
+         <item
+            android:id="@+id/draw_menu_style_brush"
+            android:title="@string/draw_style_brush" />
+         <item
+            android:id="@+id/draw_menu_size"
+            android:title="@string/draw_size" />
+        <item
+            android:id="@+id/draw_menu_color"
+            android:title="@string/draw_color"/>
+    </group>
+
+</menu>
\ No newline at end of file
diff --git a/res/values/filtershow_color.xml b/res/values/filtershow_color.xml
index 15bf2bc..175d3d3 100644
--- a/res/values/filtershow_color.xml
+++ b/res/values/filtershow_color.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2013 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.
@@ -13,6 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <resources>
     <color name="yellow">#FFFF00</color>
     <color name="green">#00FF00</color>
@@ -23,4 +24,7 @@
     <color name="background_toolbar">#363949</color>
     <color name="background_main_toolbar">#232323</color>
     <color name="toolbar_separation_line">#333333</color>
+    <color name="slider_dot_color">#6464FF</color>
+    <color name="slider_line_color">#33B5E5</color>
+
 </resources>
\ No newline at end of file
diff --git a/res/values/filtershow_ids.xml b/res/values/filtershow_ids.xml
index b45435d..c444fba 100644
--- a/res/values/filtershow_ids.xml
+++ b/res/values/filtershow_ids.xml
@@ -37,4 +37,5 @@
     <item type="id" name="drawOnImageButton" />
     <item type="id" name="imageCurves" />
     <item type="id" name="imageZoom" />
+    <item type="id" name="editorDraw" />
 </resources>
diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml
index 7fc0f4b..92cc06a 100644
--- a/res/values/filtershow_strings.xml
+++ b/res/values/filtershow_strings.xml
@@ -147,11 +147,31 @@
 
     <!--  Label for the curves tool, all channels (RGB) [CHAR LIMIT=3] -->
     <string name="curves_channel_rgb">RGB</string>
-    <!--  Label for the curves tool, Red color channel [CHAR LIMIT=10] -->
+    <!--  Label for the curves tool, Red color channel [CHAR LIMIT=14] -->
     <string name="curves_channel_red">Red</string>
-    <!--  Label for the curves tool, Green color channel [CHAR LIMIT=10] -->
+    <!--  Label for the curves tool, Green color channel [CHAR LIMIT=14] -->
     <string name="curves_channel_green">Green</string>
-    <!--  Label for the curves tool, Blue color channel [CHAR LIMIT=10] -->
+    <!--  Label for the curves tool, Blue color channel [CHAR LIMIT=14] -->
     <string name="curves_channel_blue">Blue</string>
 
+    <!--  Label for the The style to draw in [CHAR LIMIT=14] -->
+    <string name="draw_style">Style</string>
+    <!--  Label for the size to draw in in [CHAR LIMIT=14] -->
+    <string name="draw_size">Size</string>
+    <!--  Label for the color to draw in [CHAR LIMIT=14] -->
+    <string name="draw_color">Color</string>
+    <!--  Label for the line style of drawing in [CHAR LIMIT=14] -->
+    <string name="draw_style_line">Lines</string>
+    <!--  Label for the brush style of drawing in [CHAR LIMIT=14] -->
+    <string name="draw_style_brush">Brush</string>
+
+    <!--  Label for the select the color [CHAR LIMIT=30] -->
+    <string name="color_pick_select">Choose custom color</string>
+    <!--  The title for the color pick dialog [CHAR LIMIT=20] -->
+    <string name="color_pick_title">Select Color</string>
+    <!--  The title for draw size [CHAR LIMIT=50] -->
+    <string name="draw_size_title">Select Size</string>
+    <!--  The accept the draw size [CHAR LIMIT=20] -->
+    <string name="draw_size_accept">OK</string>
+
 </resources>
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index fd4eef0..7008288 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -59,6 +59,7 @@
 import com.android.gallery3d.R;
 import com.android.gallery3d.data.LocalAlbum;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
 import com.android.gallery3d.filtershow.editors.EditorManager;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -222,6 +223,7 @@
         mImageViews.add(mImageRedEyes);
 
         mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
+        mEditorPlaceHolder.addEditor(new EditorDraw());
         EditorManager.addEditors(mEditorPlaceHolder);
         mEditorPlaceHolder.setOldViews(mImageViews);
         mEditorPlaceHolder.setImageLoader(mImageLoader);
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
new file mode 100644
index 0000000..0acedb5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.android.gallery3d.R;
+
+import java.util.ArrayList;
+
+public class ColorGridDialog extends Dialog {
+    RGBListener mCallback;
+    private static final String LOGTAG = "ColorGridDialog";
+
+    public ColorGridDialog(Context context, final RGBListener cl) {
+        super(context);
+        mCallback = cl;
+        setTitle(R.string.color_pick_title);
+        setContentView(R.layout.filtershow_color_gird);
+        Button sel = (Button) findViewById(R.id.filtershow_cp_custom);
+        ArrayList<Button> b = getButtons((ViewGroup) getWindow().getDecorView());
+        int k = 0;
+        float[] hsv = new float[3];
+
+        for (Button button : b) {
+            if (!button.equals(sel)){
+                hsv[0] = (k % 5) * 360 / 5;
+                hsv[1] = (k / 5) / 3.0f;
+                hsv[2] = (k < 5) ? (k / 4f) : 1;
+                final int c = (Color.HSVToColor(hsv) & 0x00FFFFFF) | 0xAA000000;
+                GradientDrawable sd = ((GradientDrawable) button.getBackground());
+                button.setOnClickListener(new View.OnClickListener() {
+                        @Override
+                    public void onClick(View v) {
+                        mCallback.setColor(c);
+                        dismiss();
+                    }
+                });
+                sd.setColor(c);
+                k++;
+            }
+
+        }
+        sel.setOnClickListener(new View.OnClickListener() {
+                @Override
+            public void onClick(View v) {
+                showColorPicker();
+                ColorGridDialog.this.dismiss();
+            }
+        });
+    }
+
+    private ArrayList<Button> getButtons(ViewGroup vg) {
+        ArrayList<Button> list = new ArrayList<Button>();
+        for (int i = 0; i < vg.getChildCount(); i++) {
+            View v = vg.getChildAt(i);
+            if (v instanceof Button) {
+                list.add((Button) v);
+            } else if (v instanceof ViewGroup) {
+                list.addAll(getButtons((ViewGroup) v));
+            }
+        }
+        return list;
+    }
+
+    public void showColorPicker() {
+        ColorListener cl = new ColorListener() {
+                @Override
+            public void setColor(float[] hsvo) {
+                int c = Color.HSVToColor(hsvo) & 0xFFFFFF;
+                int alpha = (int) (hsvo[3] * 255);
+                c |= alpha << 24;
+                mCallback.setColor(c);
+            }
+        };
+        ColorPickerDialog cpd = new ColorPickerDialog(this.getContext(), cl);
+        cpd.show();
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java
new file mode 100644
index 0000000..5127dad
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+public interface ColorListener {
+    void setColor(float[] hsvo);
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
new file mode 100644
index 0000000..d773b6b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.gallery3d.R;
+
+import java.util.ArrayList;
+
+public class ColorOpacityView extends View implements ColorListener {
+
+    private float mRadius;
+    private float mWidth;
+    private Paint mBarPaint1;
+    private Paint mLinePaint1;
+    private Paint mLinePaint2;
+    private Paint mCheckPaint;
+
+    private float mHeight;
+    private Paint mDotPaint;
+    private int mBgcolor = 0;
+
+    private float mDotRadus;
+    private float mBorder;
+
+    private float[] mHSVO = new float[4];
+    private int mSliderColor;
+    private float mDotX = mBorder;
+    private float mDotY = mBorder;
+    private final static float DOT_SIZE = ColorRectView.DOT_SIZE;
+    public final static float BORDER_SIZE = 20;;
+
+    public ColorOpacityView(Context ctx, AttributeSet attrs) {
+        super(ctx, attrs);
+        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
+        float mDpToPix = metrics.density;
+        mDotRadus = DOT_SIZE * mDpToPix;
+        mBorder = BORDER_SIZE * mDpToPix;
+        mBarPaint1 = new Paint();
+
+        mDotPaint = new Paint();
+
+        mDotPaint.setStyle(Paint.Style.FILL);
+        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
+        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
+
+        mBarPaint1.setStyle(Paint.Style.FILL);
+
+        mLinePaint1 = new Paint();
+        mLinePaint1.setColor(Color.GRAY);
+        mLinePaint2 = new Paint();
+        mLinePaint2.setColor(mSliderColor);
+        mLinePaint2.setStrokeWidth(4);
+
+        int[] colors = new int[16 * 16];
+        for (int i = 0; i < colors.length; i++) {
+            int y = i / (16 * 8);
+            int x = (i / 8) % 2;
+            colors[i] = (x == y) ? 0xFFAAAAAA : 0xFF444444;
+        }
+        Bitmap bitmap = Bitmap.createBitmap(colors, 16, 16, Bitmap.Config.ARGB_8888);
+        BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
+        mCheckPaint = new Paint();
+        mCheckPaint.setShader(bs);
+    }
+
+    public boolean onDown(MotionEvent e) {
+        return true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        float ox = mDotX;
+        float oy = mDotY;
+
+        float x = event.getX();
+        float y = event.getY();
+
+        mDotX = x;
+
+        if (mDotX < mBorder) {
+            mDotX = mBorder;
+        }
+
+        if (mDotX > mWidth - mBorder) {
+            mDotX = mWidth - mBorder;
+        }
+        mHSVO[3] = (mDotX - mBorder) / (mWidth - mBorder * 2);
+        notifyColorListeners(mHSVO);
+        setupButton();
+        invalidate((int) (ox - mDotRadus), (int) (oy - mDotRadus), (int) (ox + mDotRadus),
+                (int) (oy + mDotRadus));
+        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
+                (int) (mDotY + mDotRadus));
+
+        return true;
+    }
+
+    private void setupButton() {
+        float pos = mHSVO[3] * (mWidth - mBorder * 2);
+        mDotX = pos + mBorder;
+
+        int[] colors3 = new int[] {
+        mSliderColor, mSliderColor, 0x66000000, 0 };
+        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[] {
+        0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+        mDotPaint.setShader(g);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        mWidth = w;
+        mHeight = h;
+        mDotY = mHeight / 2;
+        updatePaint();
+        setupButton();
+    }
+
+    private void updatePaint() {
+
+        int color2 = Color.HSVToColor(mHSVO);
+        int color1 = color2 & 0xFFFFFF;
+
+        Shader sg = new LinearGradient(
+                mBorder, mBorder, mWidth - mBorder, mBorder, color1, color2, Shader.TileMode.CLAMP);
+        mBarPaint1.setShader(sg);
+
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(mBgcolor);
+        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mCheckPaint);
+        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1);
+        canvas.drawLine(mDotX, mDotY, mWidth - mBorder, mDotY, mLinePaint1);
+        canvas.drawLine(mBorder, mDotY, mDotX, mDotY, mLinePaint2);
+        if (mDotX != Float.NaN) {
+            canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
+        }
+    }
+
+    @Override
+    public void setColor(float[] hsv) {
+        System.arraycopy(hsv, 0, mHSVO, 0, mHSVO.length);
+
+        float oy = mDotY;
+
+        updatePaint();
+        setupButton();
+        invalidate();
+    }
+
+    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
+
+    public void notifyColorListeners(float[] hsvo) {
+        for (ColorListener l : mColorListeners) {
+            l.setColor(hsvo);
+        }
+    }
+
+    public void addColorListener(ColorListener l) {
+        mColorListeners.add(l);
+    }
+
+    public void removeColorListener(ColorListener l) {
+        mColorListeners.remove(l);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
new file mode 100644
index 0000000..73a5c90
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ToggleButton;
+
+import com.android.gallery3d.R;
+
+public class ColorPickerDialog extends Dialog implements ColorListener {
+    ToggleButton mSelectedButton;
+    GradientDrawable mSelectRect;
+
+    float[] mHSVO = new float[4];
+
+    public ColorPickerDialog(Context context, final ColorListener cl) {
+        super(context);
+
+        setContentView(R.layout.filtershow_color_picker);
+        ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView);
+        ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView);
+        ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView);
+        float[] hsvo = new float[] {
+                123, .9f, 1, 1 };
+
+        mSelectRect = (GradientDrawable) getContext()
+                .getResources().getDrawable(R.drawable.filtershow_color_picker_roundrect);
+        Button selButton = (Button) findViewById(R.id.btnSelect);
+        selButton.setCompoundDrawablesWithIntrinsicBounds(null, null, mSelectRect, null);
+        Button sel = (Button) findViewById(R.id.btnSelect);
+
+        sel.setOnClickListener(new View.OnClickListener() {
+                @Override
+            public void onClick(View v) {
+                ColorPickerDialog.this.dismiss();
+                if (cl != null) {
+                    cl.setColor(mHSVO);
+                }
+            }
+        });
+
+        cwv.setColor(hsvo);
+        cvv.setColor(hsvo);
+        csv.setColor(hsvo);
+        csv.addColorListener(cwv);
+        cwv.addColorListener(csv);
+        csv.addColorListener(cvv);
+        cwv.addColorListener(cvv);
+        cvv.addColorListener(cwv);
+        cvv.addColorListener(csv);
+        cvv.addColorListener(this);
+        csv.addColorListener(this);
+        cwv.addColorListener(this);
+
+    }
+
+    void toggleClick(ToggleButton v, int[] buttons, boolean isChecked) {
+        int id = v.getId();
+        if (!isChecked) {
+            mSelectedButton = null;
+            return;
+        }
+        for (int i = 0; i < buttons.length; i++) {
+            if (id != buttons[i]) {
+                ToggleButton b = (ToggleButton) findViewById(buttons[i]);
+                b.setChecked(false);
+            }
+        }
+        mSelectedButton = v;
+
+        float[] hsv = (float[]) v.getTag();
+
+        ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView);
+        ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView);
+        ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView);
+        cwv.setColor(hsv);
+        cvv.setColor(hsv);
+        csv.setColor(hsv);
+    }
+
+    @Override
+    public void setColor(float[] hsvo) {
+        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
+        int color = Color.HSVToColor(hsvo);
+        mSelectRect.setColor(color);
+        setButtonColor(mSelectedButton, hsvo);
+    }
+
+    private void setButtonColor(ToggleButton button, float[] hsv) {
+        if (button == null) {
+            return;
+        }
+        int color = Color.HSVToColor(hsv);
+        button.setBackgroundColor(color);
+        float[] fg = new float[] {
+                (hsv[0] + 180) % 360,
+                hsv[1],
+                        (hsv[2] > .5f) ? .1f : .9f
+        };
+        button.setTextColor(Color.HSVToColor(fg));
+        button.setTag(hsv);
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
new file mode 100644
index 0000000..07d7c71
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.gallery3d.R;
+
+import java.util.ArrayList;
+
+public class ColorRectView extends View implements ColorListener {
+    private float mDpToPix;
+    private float mRadius = 80;
+    private float mCtrY = 100;
+    private Paint mWheelPaint1;
+    private Paint mWheelPaint2;
+    private Paint mWheelPaint3;
+    private float mCtrX = 100;
+    private Paint mDotPaint;
+    private float mDotRadus;
+    private float mBorder;
+    private int mBgcolor = 0;
+    private float mDotX = Float.NaN;
+    private float mDotY;
+    private int mSliderColor = 0xFF33B5E5;
+    private float[] mHSVO = new float[4];
+    private int[] mColors = new int[] {
+            0xFFFF0000,// red
+            0xFFFFFF00,// yellow
+            0xFF00FF00,// green
+            0xFF00FFFF,// cyan
+            0xFF0000FF,// blue
+            0xFFFF00FF,// magenta
+            0xFFFF0000,// red
+    };
+    private int mWidth;
+    private int mHeight;
+    public final static float DOT_SIZE = 20;
+    public final static float BORDER_SIZE = 10;
+
+    public ColorRectView(Context ctx, AttributeSet attrs) {
+        super(ctx, attrs);
+
+        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
+        mDpToPix = metrics.density;
+        mDotRadus = DOT_SIZE * mDpToPix;
+        mBorder = BORDER_SIZE * mDpToPix;
+
+        mWheelPaint1 = new Paint();
+        mWheelPaint2 = new Paint();
+        mWheelPaint3 = new Paint();
+        mDotPaint = new Paint();
+
+        mDotPaint.setStyle(Paint.Style.FILL);
+        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
+        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
+        mWheelPaint1.setStyle(Paint.Style.FILL);
+        mWheelPaint2.setStyle(Paint.Style.FILL);
+        mWheelPaint3.setStyle(Paint.Style.FILL);
+    }
+
+    public boolean onDown(MotionEvent e) {
+        return true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+
+        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
+                (int) (mDotY + mDotRadus));
+        float x = event.getX();
+        float y = event.getY();
+
+        x = Math.max(Math.min(x, mWidth - mBorder), mBorder);
+        y = Math.max(Math.min(y, mHeight - mBorder), mBorder);
+        mDotX = x;
+        mDotY = y;
+        float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder);
+        if (sat > 1) {
+            sat = 1;
+        }
+
+        double hue = Math.PI * 2 * (mDotX - mBorder) / (mHeight - 2 * mBorder);
+        mHSVO[0] = ((float) Math.toDegrees(hue) + 360) % 360;
+        mHSVO[1] = sat;
+        notifyColorListeners(mHSVO);
+        updateDotPaint();
+        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
+                (int) (mDotY + mDotRadus));
+
+        return true;
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        mWidth = w;
+        mHeight = h;
+        mCtrY = h / 2f;
+        mCtrX = w / 2f;
+        mRadius = Math.min(mCtrY, mCtrX) - 2 * mBorder;
+        setUpColorPanel();
+    }
+
+    private void setUpColorPanel() {
+        float val = mHSVO[2];
+        int v = 0xFF000000 | 0x10101 * (int) (val * 0xFF);
+        int[] colors = new int[] {
+                0x0000000, v };
+        int[] colors2 = new int[] {
+                0x0000000, 0xFF000000 };
+        int[] wheelColor = new int[mColors.length];
+        float[] hsv = new float[3];
+        for (int i = 0; i < wheelColor.length; i++) {
+            Color.colorToHSV(mColors[i], hsv);
+            hsv[2] = mHSVO[2];
+            wheelColor[i] = Color.HSVToColor(hsv);
+        }
+        updateDot();
+        updateDotPaint();
+        SweepGradient sg = new SweepGradient(mCtrX, mCtrY, wheelColor, null);
+        LinearGradient lg = new LinearGradient(
+                mBorder, 0, mWidth - mBorder, 0, wheelColor, null, Shader.TileMode.CLAMP);
+
+        mWheelPaint1.setShader(lg);
+        LinearGradient rg = new LinearGradient(
+                0, mBorder, 0, mHeight - mBorder, colors, null, Shader.TileMode.CLAMP);
+        mWheelPaint2.setShader(rg);
+        LinearGradient rg2 = new LinearGradient(
+                0, mBorder, 0, mHeight - mBorder, colors2, null, Shader.TileMode.CLAMP);
+        mWheelPaint3.setShader(rg2);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(mBgcolor);
+        RectF rect = new RectF();
+        rect.left = mBorder;
+        rect.right = mWidth - mBorder;
+        rect.top = mBorder;
+        rect.bottom = mHeight - mBorder;
+
+        canvas.drawRect(rect, mWheelPaint1);
+        canvas.drawRect(rect, mWheelPaint3);
+        canvas.drawRect(rect, mWheelPaint2);
+
+        if (mDotX != Float.NaN) {
+
+            canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
+        }
+    }
+
+    private void updateDot() {
+
+        double hue = mHSVO[0];
+        double sat = mHSVO[1];
+
+        mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * Math.toRadians(hue) / (Math.PI * 2));
+        mDotY = (float) ((1 - sat) * (mHeight - 2 * mBorder) + mBorder);
+
+    }
+
+    private void updateDotPaint() {
+        int[] colors3 = new int[] {
+                mSliderColor, mSliderColor, 0x66000000, 0 };
+        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[] {
+                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+        mDotPaint.setShader(g);
+
+    }
+
+    @Override
+    public void setColor(float[] hsvo) {
+        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
+
+        setUpColorPanel();
+        invalidate();
+
+        updateDot();
+        updateDotPaint();
+
+    }
+
+    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
+
+    public void notifyColorListeners(float[] hsv) {
+        for (ColorListener l : mColorListeners) {
+            l.setColor(hsv);
+        }
+    }
+
+    public void addColorListener(ColorListener l) {
+        mColorListeners.add(l);
+    }
+
+    public void removeColorListener(ColorListener l) {
+        mColorListeners.remove(l);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
new file mode 100644
index 0000000..13cb44b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.gallery3d.R;
+
+import java.util.ArrayList;
+
+public class ColorValueView extends View implements ColorListener {
+
+    private float mRadius;
+    private float mWidth;
+    private Paint mBarPaint1;
+    private Paint mLinePaint1;
+    private Paint mLinePaint2;
+    private float mHeight;
+    private int mBgcolor = 0;
+    private Paint mDotPaint;
+    private float dotRadus;
+    private float mBorder;
+
+    private float[] mHSVO = new float[4];
+    private int mSliderColor;
+    private float mDotX;
+    private float mDotY = mBorder;
+    private final static float DOT_SIZE = ColorRectView.DOT_SIZE;
+    private final static float BORDER_SIZE = ColorRectView.DOT_SIZE;
+
+    public ColorValueView(Context ctx, AttributeSet attrs) {
+        super(ctx, attrs);
+        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
+        float mDpToPix = metrics.density;
+        dotRadus = DOT_SIZE * mDpToPix;
+        mBorder = BORDER_SIZE * mDpToPix;
+
+        mBarPaint1 = new Paint();
+
+        mDotPaint = new Paint();
+
+        mDotPaint.setStyle(Paint.Style.FILL);
+        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
+
+        mBarPaint1.setStyle(Paint.Style.FILL);
+
+        mLinePaint1 = new Paint();
+        mLinePaint1.setColor(Color.GRAY);
+        mLinePaint2 = new Paint();
+        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
+        mLinePaint2.setColor(mSliderColor);
+        mLinePaint2.setStrokeWidth(4);
+    }
+
+    public boolean onDown(MotionEvent e) {
+        return true;
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        float ox = mDotX;
+        float oy = mDotY;
+
+        float x = event.getX();
+        float y = event.getY();
+
+        mDotY = y;
+
+        if (mDotY < mBorder) {
+            mDotY = mBorder;
+        }
+
+        if (mDotY > mHeight - mBorder) {
+            mDotY = mHeight - mBorder;
+        }
+        mHSVO[2] = (mDotY - mBorder) / (mHeight - mBorder * 2);
+        notifyColorListeners(mHSVO);
+        setupButton();
+        invalidate((int) (ox - dotRadus), (int) (oy - dotRadus), (int) (ox + dotRadus),
+                (int) (oy + dotRadus));
+        invalidate((int) (mDotX - dotRadus), (int) (mDotY - dotRadus), (int) (mDotX + dotRadus),
+                (int) (mDotY + dotRadus));
+
+        return true;
+    }
+
+    private void setupButton() {
+        float pos = mHSVO[2] * (mHeight - mBorder * 2);
+        mDotY = pos + mBorder;
+
+        int[] colors3 = new int[] {
+                mSliderColor, mSliderColor, 0x66000000, 0 };
+        RadialGradient g = new RadialGradient(mDotX, mDotY, dotRadus, colors3, new float[] {
+        0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+        mDotPaint.setShader(g);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        mWidth = w;
+        mHeight = h;
+        mDotX = mWidth / 2;
+        updatePaint();
+        setupButton();
+    }
+
+    private void updatePaint() {
+        float[] hsv = new float[] {
+                mHSVO[0], mHSVO[1], 0f };
+        int color1 = Color.HSVToColor(hsv);
+        hsv[2] = 1;
+        int color2 = Color.HSVToColor(hsv);
+
+        Shader sg = new LinearGradient(mBorder, mBorder, mBorder, mHeight - mBorder, color1, color2,
+                Shader.TileMode.CLAMP);
+        mBarPaint1.setShader(sg);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(mBgcolor);
+        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1);
+        canvas.drawLine(mDotX, mDotY, mDotX, mHeight - mBorder, mLinePaint2);
+        canvas.drawLine(mDotX, mBorder, mDotX, mDotY, mLinePaint1);
+        if (mDotX != Float.NaN) {
+            canvas.drawCircle(mDotX, mDotY, dotRadus, mDotPaint);
+        }
+    }
+
+    @Override
+    public void setColor(float[] hsvo) {
+        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
+
+        float oy = mDotY;
+        updatePaint();
+        setupButton();
+        invalidate();
+
+    }
+
+    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
+
+    public void notifyColorListeners(float[] hsv) {
+        for (ColorListener l : mColorListeners) {
+            l.setColor(hsv);
+        }
+    }
+
+    public void addColorListener(ColorListener l) {
+        mColorListeners.add(l);
+    }
+
+    public void removeColorListener(ColorListener l) {
+        mColorListeners.remove(l);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java b/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java
new file mode 100644
index 0000000..147fb91
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.colorpicker;
+
+public interface RGBListener {
+    void setColor(int hsv);
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
new file mode 100644
index 0000000..abd4ae4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013 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.android.gallery3d.filtershow.editors;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.PopupMenu;
+import android.widget.SeekBar;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.colorpicker.ColorGridDialog;
+import com.android.gallery3d.filtershow.colorpicker.RGBListener;
+import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
+import com.android.gallery3d.filtershow.imageshow.ImageDraw;
+import com.android.gallery3d.filtershow.ui.FramedTextButton;
+
+/**
+ * TODO: Insert description here. (generated by hoford)
+ */
+public class EditorDraw extends Editor {
+    private static final String LOGTAG = "EditorDraw";
+    public static final int ID = R.id.editorDraw;
+
+    public EditorDraw() {
+        super(ID);
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mView = mImageShow = new ImageDraw(context);
+    }
+
+    @Override
+    public boolean useUtilityPanel() {
+        return true;
+    }
+
+    @Override
+    public void openUtilityPanel(final LinearLayout accessoryViewList) {
+        View view = accessoryViewList.findViewById(R.id.drawUtilityButton);
+        if (view == null) {
+            LayoutInflater inflater = (LayoutInflater) mImageShow.getActivity().getSystemService
+                    (Context.LAYOUT_INFLATER_SERVICE);
+            view = inflater.inflate(R.layout.filtershow_draw_button, accessoryViewList, false);
+            accessoryViewList.addView(view, view.getLayoutParams());
+            view.setOnClickListener(new OnClickListener() {
+                    @Override
+                public void onClick(View arg0) {
+                    showPopupMenu(accessoryViewList);
+                }
+            });
+        }
+
+        if (view != null) {
+            view.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private void showPopupMenu(LinearLayout accessoryViewList) {
+        final FramedTextButton button = (FramedTextButton) accessoryViewList.findViewById(
+                R.id.drawUtilityButton);
+        if (button == null) {
+            return;
+        }
+        PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button);
+        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_draw, popupMenu.getMenu());
+        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+            @Override
+            public boolean onMenuItemClick(MenuItem item) {
+                ImageFilterDraw filter = (ImageFilterDraw) mImageShow.getCurrentFilter();
+                int minp = filter.getMinParameter();
+                int parameter = filter.getParameter();
+                if (item.getItemId() == R.id.draw_menu_color) {
+                    showColorGrid(item);
+                } else if (item.getItemId() == R.id.draw_menu_size) {
+                    showSizeDialog(item);
+                } else if (item.getItemId() == R.id.draw_menu_style_brush) {
+                    ImageDraw idraw = (ImageDraw) mImageShow;
+                    idraw.setStyle(ImageFilterDraw.BRUSH_STYLE);
+                } else if (item.getItemId() == R.id.draw_menu_style_line) {
+                    ImageDraw idraw = (ImageDraw) mImageShow;
+                    idraw.setStyle(ImageFilterDraw.SIMPLE_STYLE);
+
+                }
+                mView.invalidate();
+                return true;
+            }
+        });
+        popupMenu.show();
+    }
+
+    public void showSizeDialog(final MenuItem item) {
+        FilterShowActivity ctx = mImageShow.getActivity();
+        final Dialog dialog = new Dialog(ctx);
+        dialog.setTitle(R.string.draw_size_title);
+        dialog.setContentView(R.layout.filtershow_draw_size);
+        final SeekBar bar = (SeekBar) dialog.findViewById(R.id.sizeSeekBar);
+        ImageDraw idraw = (ImageDraw) mImageShow;
+        bar.setProgress(idraw.getSize());
+        Button button = (Button) dialog.findViewById(R.id.sizeAcceptButton);
+        button.setOnClickListener(new OnClickListener() {
+
+            public void onClick(View arg0) {
+                int p = bar.getProgress();
+                ImageDraw idraw = (ImageDraw) mImageShow;
+                idraw.setSize(p + 1);
+                dialog.dismiss();
+            }
+        });
+        dialog.show();
+    }
+    public void showColorGrid(final MenuItem item) {
+        RGBListener cl = new RGBListener() {
+                @Override
+            public void setColor(int rgb) {
+                ImageDraw idraw = (ImageDraw) mImageShow;
+                idraw.setColor(rgb);
+            }
+        };
+        ColorGridDialog cpd = new ColorGridDialog(mImageShow.getActivity(), cl);
+        cpd.show();
+        LayoutParams params = cpd.getWindow().getAttributes();
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
index cadcbb3..fac9e99 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
@@ -21,27 +21,29 @@
 import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.RectF;
-import android.graphics.Xfermode;
 import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
 import android.util.Log;
 
 import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
 
 import java.util.Arrays;
-import java.util.Vector;
 
 public class ImageFilterDraw extends ImageFilter {
     private static final String LOGTAG = "ImageFilterDraw";
-
-    final float STROKE_RADIUS = 40;
+    public final static char SIMPLE_STYLE = 0;
+    public final static char BRUSH_STYLE = 1;
     Bitmap mOverlayBitmap; // this accelerates interaction
-    int   mCachedStrokes =-1;
-    SimpleDraw mSimpleDraw = new SimpleDraw();
+    int mCachedStrokes = -1;
+    int mCurrentStyle = 0;
+    DrawStyle[] mDrawings = new DrawStyle[] {
+            new SimpleDraw(), new Brush() };
+
+    public void setStyle(char style) {
+        mCurrentStyle = style;
+    }
 
     public static interface DrawStyle {
         public DrawStyle clone();
@@ -55,6 +57,7 @@
         public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality);
         public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality);
         public boolean same(DrawStyle o);
+        public boolean empty();
     };
 
     class SimpleDraw implements DrawStyle {
@@ -67,10 +70,11 @@
         private float mCurrentRadius;
         private int mCurrentColor;
 
+        @Override
         public DrawStyle clone() {
             SimpleDraw ret = new SimpleDraw();
             ret.mPaths = new Path[mPaths.length];
-            for (int i = 0; i < mPaths.length; i++) {
+            for (int i = 0; i < ret.mPaths.length; i++) {
                 ret.mPaths[i] = new Path(mPaths[i]);
             }
             ret.mColors = Arrays.copyOf(mColors, mColors.length);
@@ -79,25 +83,35 @@
             return ret;
         }
 
+        @Override
+        public boolean empty() {
+            return mStrokeCnt == -1;
+        }
+
+        @Override
         public void setSize(float radius) {
             mCurrentRadius = radius;
         }
 
+        @Override
         public void setColor(int color) {
             mCurrentColor = color;
         }
 
+        @Override
         public void startStroke(float x, float y) {
             mCurrentPath = new Path();
             mCurrentPath.moveTo(x, y);
         }
 
+        @Override
         public void stroke(float x, float y) {
             if (mCurrentPath != null) {
                 mCurrentPath.lineTo(x, y);
             }
         }
 
+        @Override
         public void endStroke(float x, float y) {
             if (mCurrentPath != null) {
                 mCurrentPath.lineTo(x, y);
@@ -114,13 +128,18 @@
                 mStrokeCnt++;
             }
         }
+
+        @Override
         public void clearCurren(){
             mCurrentPath = null;
         }
+
+        @Override
         public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
             Path path = mCurrentPath;
-            if (path == null)
+            if (path == null) {
                 return;
+            }
             Paint paint = new Paint();
 
             paint.setStyle(Style.STROKE);
@@ -134,6 +153,7 @@
             canvas.drawPath(mCacheTransPath, paint);
         }
 
+        @Override
         public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
             Paint paint = new Paint();
             Matrix m = new Matrix();
@@ -149,6 +169,7 @@
             return mStrokeCnt;
         }
 
+        @Override
         public boolean same(DrawStyle o) {
             if (!(o instanceof SimpleDraw)) {
                 return false;
@@ -171,23 +192,177 @@
             return true;
         }
 
+        @Override
         public int getNumberOfStrokes() {
             return mStrokeCnt;
         }
     }
 
-    public void startSection(int color, float x, float y) {
-        mSimpleDraw.setColor(color);
-        mSimpleDraw.setSize(STROKE_RADIUS);
-        mSimpleDraw.startStroke(x, y);
+    class Brush implements DrawStyle {
+        private Path[] mPaths = new Path[0];
+        private int[] mColors = new int[0];
+        private float[] mRadius = new float[0];
+        private int mStrokeCnt = 0;
+
+        private Path mCurrentPath;
+        private float mCurrentRadius;
+        private int mCurrentColor;
+
+        @Override
+        public DrawStyle clone() {
+            Brush ret = new Brush();
+            ret.mPaths = new Path[mPaths.length];
+            for (int i = 0; i < ret.mPaths.length; i++) {
+                ret.mPaths[i] = new Path(mPaths[i]);
+            }
+            ret.mColors = Arrays.copyOf(mColors, mColors.length);
+            ret.mRadius = Arrays.copyOf(mRadius, mRadius.length);
+            ret.mStrokeCnt = mStrokeCnt;
+            return ret;
+        }
+
+        @Override
+        public boolean empty() {
+            return mStrokeCnt == -1;
+        }
+
+        @Override
+        public void setSize(float radius) {
+            mCurrentRadius = radius;
+        }
+
+        @Override
+        public void setColor(int color) {
+            mCurrentColor = color;
+        }
+
+        @Override
+        public void startStroke(float x, float y) {
+            mCurrentPath = new Path();
+            mCurrentPath.moveTo(x, y);
+        }
+
+        @Override
+        public void stroke(float x, float y) {
+            if (mCurrentPath != null) {
+                mCurrentPath.lineTo(x, y);
+            }
+        }
+
+        @Override
+        public void endStroke(float x, float y) {
+            if (mCurrentPath != null) {
+                mCurrentPath.lineTo(x, y);
+                Path[] np = new Path[mStrokeCnt + 1];
+                for (int i = 0; i < mStrokeCnt; i++) {
+                    np[i] = mPaths[i];
+                }
+                np[mStrokeCnt] = mCurrentPath;
+                mColors = Arrays.copyOf(mColors, mColors.length + 1);
+                mRadius = Arrays.copyOf(mRadius, mRadius.length + 1);
+                mRadius[mStrokeCnt] = mCurrentRadius;
+                mColors[mStrokeCnt] = mCurrentColor;
+                mPaths = np;
+                mStrokeCnt++;
+                clearCurren();
+            }
+        }
+
+        @Override
+        public void clearCurren() {
+            mCurrentPath = null;
+        }
+
+        @Override
+        public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
+            Path path = mCurrentPath;
+            if (path == null) {
+                return;
+            }
+            Paint paint = new Paint();
+
+            canvas.save();
+            canvas.concat(toScrMatrix);
+            paint.setStyle(Style.STROKE);
+
+            float scale = toScrMatrix.mapRadius(1);
+            draw(canvas, paint, mCurrentColor, mCurrentRadius, path);
+            canvas.restore();
+        }
+
+        @Override
+        public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
+            Paint paint = new Paint();
+
+            Matrix m = new Matrix();
+            canvas.save();
+            canvas.concat(toScrMatrix);
+            paint.setStyle(Style.STROKE);
+            for (int i = from; i < mStrokeCnt; i++) {
+
+                draw(canvas, paint, mColors[i], mRadius[i], mPaths[i]);
+            }
+            canvas.restore();
+            return mStrokeCnt;
+        }
+
+        PathMeasure mPathMeasure = new PathMeasure();
+
+        void draw(Canvas canvas, Paint paint, int color, float size, Path path) {
+
+            mPathMeasure.setPath(path, false);
+            float[] pos = new float[2];
+            float[] tan = new float[2];
+            paint.setColor(color);
+            float len = mPathMeasure.getLength();
+            for (float i = 0; i < len; i += (size) / 2) {
+                mPathMeasure.getPosTan(i, pos, tan);
+                canvas.drawCircle(pos[0], pos[1], size, paint);
+            }
+
+        }
+
+        @Override
+        public boolean same(DrawStyle o) {
+            if (!(o instanceof Brush)) {
+                return false;
+            }
+            Brush sd = (Brush) o;
+            boolean same;
+            same = Arrays.equals(mRadius, sd.mRadius);
+            if (!same) {
+                return false;
+            }
+            same = Arrays.equals(mColors, sd.mColors);
+            if (!same) {
+                return false;
+            }
+            for (int i = 0; i < mPaths.length; i++) {
+                if (!mPaths[i].equals(sd.mPaths)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public int getNumberOfStrokes() {
+            return mStrokeCnt;
+        }
+    }
+
+    public void startSection(int color, float size, float x, float y) {
+        mDrawings[mCurrentStyle].setColor(color);
+        mDrawings[mCurrentStyle].setSize(size);
+        mDrawings[mCurrentStyle].startStroke(x, y);
     }
 
     public void addPoint(float x, float y) {
-        mSimpleDraw.stroke(x, y);
+        mDrawings[mCurrentStyle].stroke(x, y);
     }
 
     public void endSection(float x, float y) {
-        mSimpleDraw.endStroke(x, y);
+        mDrawings[mCurrentStyle].endStroke(x, y);
     }
 
     public ImageFilterDraw() {
@@ -202,11 +377,18 @@
         paint.setStyle(Style.STROKE);
         paint.setColor(Color.RED);
         paint.setStrokeWidth(40);
-        if (mSimpleDraw.mStrokeCnt == -1) {
+        boolean empty = true;
+        for (int i = 0; i < mDrawings.length; i++) {
+            empty &= mDrawings[i].empty();
+        }
+        if (empty) {
             return;
         }
         if (highQuality) {
-            mSimpleDraw.paintLast(0, canvas, originalRotateToScreen, highQuality);
+            for (int i = 0; i < mDrawings.length; i++) {
+                mDrawings[i].paintLast(0, canvas, originalRotateToScreen, highQuality);
+            }
+
             return;
         }
         if (mOverlayBitmap == null ||
@@ -217,22 +399,19 @@
                     canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
             mCachedStrokes = 0;
         }
-        if (mCachedStrokes < mSimpleDraw.getNumberOfStrokes()) {
+        if (mCachedStrokes < mDrawings[mCurrentStyle].getNumberOfStrokes()) {
             fillBuffer(originalRotateToScreen);
         }
         canvas.drawBitmap(mOverlayBitmap, 0, 0, paint);
     }
 
     public void fillBuffer(Matrix originalRotateToScreen) {
-        Paint paint = new Paint();
-        paint.setStyle(Style.STROKE);
-        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
-        paint.setStrokeWidth(STROKE_RADIUS);
-
         Canvas drawCache = new Canvas(mOverlayBitmap);
-        mCachedStrokes = mSimpleDraw.paintLast(
-                mCachedStrokes, drawCache, originalRotateToScreen, false);
+        for (int i = 0; i < mDrawings.length; i++) {
 
+            mCachedStrokes = mDrawings[i].paintLast(
+                mCachedStrokes, drawCache, originalRotateToScreen, false);
+        }
     }
 
     @Override
@@ -247,21 +426,23 @@
 
     @Override
     public int getEditingViewId() {
-        return R.id.imageDraw;
+        return EditorDraw.ID;
     }
 
     @Override
     public ImageFilter clone() throws CloneNotSupportedException {
         ImageFilterDraw filter = (ImageFilterDraw) super.clone();
 
-        filter.mSimpleDraw = (SimpleDraw) mSimpleDraw.clone();
+        filter.mDrawings = mDrawings.clone();
         return filter;
     }
 
     @Override
     public boolean isNil() {
-        if (mSimpleDraw.getNumberOfStrokes() != 0) {
-            return false;
+        for (int i = 0; i < mDrawings.length; i++) {
+            if (mDrawings[i].getNumberOfStrokes() != 0) {
+                return false;
+            }
         }
         return true;
     }
@@ -274,15 +455,21 @@
         }
 
         ImageFilterDraw dfilter = (ImageFilterDraw) filter;
-        return mSimpleDraw.same(dfilter.mSimpleDraw);
+        boolean same = true;
+        for (int i = 0; i < mDrawings.length; i++) {
+            same &= mDrawings[i].same(dfilter.mDrawings[i]);
+        }
+        return same;
     }
 
     public void clear() {
-        mSimpleDraw.clearCurren();
+        mDrawings[mCurrentStyle].clearCurren();
     }
 
     public void draw(Canvas canvas, Matrix originalRotateToScreen) {
-        mSimpleDraw.paintCurrentStroke(canvas, originalRotateToScreen, false);
+        for (int i = 0; i < mDrawings.length; i++) {
+            mDrawings[i].paintCurrentStroke(canvas, originalRotateToScreen, false);
+        }
     }
 
     @Override
@@ -298,5 +485,4 @@
 
         return bitmap;
     }
-
 }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
index 16c2422..16076fd 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
@@ -18,6 +18,9 @@
 public class ImageDraw extends ImageShow {
 
     private static final String LOGTAG = "ImageDraw";
+    private int mCurrentColor = Color.RED;
+    final static float INITAL_STROKE_RADIUS = 40;
+    private float mCurrentSize = INITAL_STROKE_RADIUS;
 
     public ImageDraw(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -33,8 +36,23 @@
         if (filter != null) {
             filter.clear();
         }
+    }
 
-        invalidate();
+    public void setColor(int color) {
+        mCurrentColor = color;
+    }
+
+    public void setSize(int size) {
+        mCurrentSize = size;
+    }
+
+    public void setStyle(char style) {
+        ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
+        filter.setStyle(style);
+    }
+
+    public int getSize() {
+        return (int) mCurrentSize;
     }
 
     @Override
@@ -57,12 +75,7 @@
             mTmpPoint[0] = event.getX();
             mTmpPoint[1] = event.getY();
             mToOrig.mapPoints(mTmpPoint);
-            float[] hsv = new float[3];
-            hsv[0] = (float) (360 * Math.random());
-            hsv[1] = 1;
-            hsv[2] = 1;
-            int col = Color.HSVToColor(0x88, hsv);
-            filter.startSection(col, mTmpPoint[0], mTmpPoint[1]);
+            filter.startSection(mCurrentColor, mCurrentSize, mTmpPoint[0], mTmpPoint[1]);
 
         }
         if (event.getAction() == MotionEvent.ACTION_MOVE) {
@@ -109,10 +122,11 @@
     @Override
     public void onDraw(Canvas canvas) {
         super.onDraw(canvas);
-
-        calcScreenMapping();
-
         ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
-        filter.draw(canvas, mRotateToScreen);
+        if (filter != null) {
+            calcScreenMapping();
+            filter.draw(canvas, mRotateToScreen);
+        }
     }
+
 }
diff --git a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
index 0c73183..68fefa1 100644
--- a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
@@ -27,6 +27,7 @@
         editorPlaceHolder.addEditor(new EditorZoom());
         editorPlaceHolder.addEditor(new EditorCurves());
         editorPlaceHolder.addEditor(new BasicEditor());
+        editorPlaceHolder.addEditor(new EditorDraw());
     }
 
 }