Merge "Don't use translated strings for video sized until they're sane." into ub-camera-everglades
diff --git a/res/layout/settings_cling.xml b/res/layout/settings_cling.xml
new file mode 100644
index 0000000..406a016
--- /dev/null
+++ b/res/layout/settings_cling.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.camera.widget.SettingsCling xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/settings_cling"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:visibility="invisible"
+    android:paddingTop="@dimen/settings_cling_triangle_height"
+    android:paddingBottom="@dimen/settings_cling_triangle_height">
+    <TextView
+      android:layout_width="@dimen/settings_cling_width"
+      android:layout_height="wrap_content"
+      android:text="@string/settings_cling_text"
+      android:background="@drawable/btn_cling"
+      android:textColor="@android:color/white"
+      android:layout_gravity="top|left"/>
+</com.android.camera.widget.SettingsCling>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 4fd2935..adce58c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -102,4 +102,6 @@
     <color name="start_up_dialog_background_color">#D6D6D6</color>
     <color name="dialog_button_color">#FF76A7F9</color>
     <color name="dialog_text_color">#6D6D6D</color>
+
+    <color name="settings_cling_color">#FF76A7F9</color>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d00b586..31e8550 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -203,4 +203,7 @@
     <dimen name="video_hint_phone_graphic_height">66dp</dimen>
     <dimen name="video_hint_phone_graphic_width">36dp</dimen>
     <dimen name="default_cling_width">120dp</dimen>
+    <dimen name="settings_cling_width">160dp</dimen>
+    <dimen name="settings_cling_triangle_height">15dp</dimen>
+    <dimen name="settings_cling_triangle_width">20dp</dimen>
 </resources>
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index 2f55f02..e8d7290 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -758,6 +758,9 @@
             mModeListView.setModeListOpenListener(this);
             mModeListView.setCameraModuleScreenShotProvider(mCameraModuleScreenShotProvider);
             mModeListView.setCaptureLayoutHelper(mCaptureLayoutHelper);
+            boolean shouldShowSettingsCling = mController.getSettingsManager().getBoolean(
+                    SettingsManager.SETTING_SHOULD_SHOW_SETTINGS_BUTTON_CLING);
+            mModeListView.setShouldShowSettingsCling(shouldShowSettingsCling);
         } else {
             Log.e(TAG, "Cannot find mode list in the view hierarchy");
         }
@@ -1381,6 +1384,9 @@
 
     @Override
     public void onSettingsSelected() {
+        mController.getSettingsManager()
+                .setBoolean(SettingsManager.SETTING_SHOULD_SHOW_SETTINGS_BUTTON_CLING, false);
+        mModeListView.setShouldShowSettingsCling(false);
         mController.onSettingsSelected();
     }
 
diff --git a/src/com/android/camera/settings/SettingsCache.java b/src/com/android/camera/settings/SettingsCache.java
index bdd9253..f0986d9 100644
--- a/src/com/android/camera/settings/SettingsCache.java
+++ b/src/com/android/camera/settings/SettingsCache.java
@@ -139,6 +139,8 @@
                 SettingsManager.SETTING_USER_SELECTED_ASPECT_RATIO);
         mKeyMap.put(SettingsManager.KEY_COUNTDOWN_DURATION,
                 SettingsManager.SETTING_COUNTDOWN_DURATION);
+        mKeyMap.put(SettingsManager.KEY_SHOULD_SHOW_SETTINGS_BUTTON_CLING,
+                SettingsManager.SETTING_SHOULD_SHOW_SETTINGS_BUTTON_CLING);
     }
 
     /**
@@ -229,6 +231,8 @@
                 return SettingsManager.getUserSelectedAspectRatioSetting(mContext);
             case SettingsManager.SETTING_COUNTDOWN_DURATION:
                 return SettingsManager.getCountDownDurationSetting(mContext);
+            case SettingsManager.SETTING_SHOULD_SHOW_SETTINGS_BUTTON_CLING:
+                return SettingsManager.getShouldShowSettingsButtonCling(mContext);
             default:
                 return mExtraSettings.settingFromId(id, mContext);
         }
diff --git a/src/com/android/camera/settings/SettingsManager.java b/src/com/android/camera/settings/SettingsManager.java
index 0270922..113079a 100644
--- a/src/com/android/camera/settings/SettingsManager.java
+++ b/src/com/android/camera/settings/SettingsManager.java
@@ -441,6 +441,7 @@
     public static final int SETTING_EXPOSURE_COMPENSATION_ENABLED = 32;
     public static final int SETTING_USER_SELECTED_ASPECT_RATIO = 33;
     public static final int SETTING_COUNTDOWN_DURATION = 34;
+    public static final int SETTING_SHOULD_SHOW_SETTINGS_BUTTON_CLING = 35;
 
     // Shared preference keys.
     public static final String KEY_RECORD_LOCATION = "pref_camera_recordlocation_key";
@@ -481,6 +482,8 @@
             "pref_camera_exposure_compensation_key";
     public static final String KEY_USER_SELECTED_ASPECT_RATIO = "pref_user_selected_aspect_ratio";
     public static final String KEY_COUNTDOWN_DURATION = "pref_camera_countdown_duration_key";
+    public static final String KEY_SHOULD_SHOW_SETTINGS_BUTTON_CLING =
+            "pref_should_show_settings_button_cling";
 
     public static final int WHITE_BALANCE_DEFAULT_INDEX = 2;
 
@@ -1218,6 +1221,11 @@
                 KEY_SHOULD_SHOW_REFOCUS_VIEWER_CLING, null, FLUSH_OFF);
     }
 
+    public static Setting getShouldShowSettingsButtonCling(Context context) {
+        return new Setting(SOURCE_DEFAULT, TYPE_BOOLEAN, VALUE_ON,
+                KEY_SHOULD_SHOW_SETTINGS_BUTTON_CLING, null, FLUSH_OFF);
+    }
+
     // Utilities.
 
     /**
diff --git a/src/com/android/camera/ui/ModeListView.java b/src/com/android/camera/ui/ModeListView.java
index e74b3b0..a41ee03 100644
--- a/src/com/android/camera/ui/ModeListView.java
+++ b/src/com/android/camera/ui/ModeListView.java
@@ -46,6 +46,7 @@
 import com.android.camera.util.Gusterpolator;
 import com.android.camera.util.UsageStatistics;
 import com.android.camera.widget.AnimationEffects;
+import com.android.camera.widget.SettingsCling;
 import com.android.camera2.R;
 import com.google.common.logging.eventprotos;
 
@@ -134,6 +135,7 @@
     private float mVelocityX; // Unit: pixel/ms.
     private long mLastDownTime = 0;
     private CaptureLayoutHelper mCaptureLayoutHelper = null;
+    private SettingsCling mSettingsCling = null;
 
     private class CurrentStateManager {
         private ModeListState mCurrentState;
@@ -163,6 +165,7 @@
          */
         public void onCurrentState() {
             // Do nothing.
+            showSettingsClingIfEnabled(false);
         }
 
         /**
@@ -404,8 +407,9 @@
 
         @Override
         public void onCurrentState() {
-          announceForAccessibility(
-                  getContext().getResources().getString(R.string.accessibility_mode_list_hidden));
+            super.onCurrentState();
+            announceForAccessibility(
+                    getContext().getResources().getString(R.string.accessibility_mode_list_hidden));
         }
 
     }
@@ -525,8 +529,9 @@
 
         @Override
         public void onCurrentState() {
-          announceForAccessibility(
-                  getContext().getResources().getString(R.string.accessibility_mode_list_shown));
+            announceForAccessibility(
+                    getContext().getResources().getString(R.string.accessibility_mode_list_shown));
+            showSettingsClingIfEnabled(true);
         }
 
     }
@@ -732,10 +737,6 @@
             mCurrentStateManager.setCurrentState(new FullyHiddenState());
         }
 
-        @Override
-        public void onCurrentState() {
-        }
-
     }
 
     /**
@@ -1383,6 +1384,9 @@
             mSettingsButton.setTranslationY(uncoveredPreviewArea.bottom - mSettingsButtonMargin
                     - mSettingsButton.getMeasuredHeight());
         }
+        if (mSettingsCling != null) {
+            mSettingsCling.updatePosition(mSettingsButton);
+        }
     }
 
     @Override
@@ -1401,6 +1405,40 @@
     }
 
     /**
+     * Sets whether a cling for settings button should be shown. If not, remove
+     * the cling from view hierarchy if any. If a cling should be shown, inflate
+     * the cling into this view group.
+     *
+     * @param show whether the cling needs to be shown.
+     */
+    public void setShouldShowSettingsCling(boolean show) {
+        if (show) {
+            if (mSettingsCling == null) {
+                inflate(getContext(), R.layout.settings_cling, this);
+                mSettingsCling = (SettingsCling) findViewById(R.id.settings_cling);
+            }
+        } else {
+            if (mSettingsCling != null) {
+                // Remove settings cling from view hierarchy.
+                removeView(mSettingsCling);
+                mSettingsCling = null;
+            }
+        }
+    }
+
+    /**
+     * Show or hide cling for settings button. The cling will only be shown if
+     * settings button has never been clicked. Otherwise, cling will be null,
+     * and will not show even if this method is called to show it.
+     */
+    private void showSettingsClingIfEnabled(boolean show) {
+        if (mSettingsCling != null) {
+            int visibility = show ? VISIBLE : INVISIBLE;
+            mSettingsCling.setVisibility(visibility);
+        }
+    }
+
+    /**
      * This shows the mode switcher and starts the accordion animation with a delay.
      * If the view does not currently have focus, (e.g. There are popups on top of
      * it.) start the delayed accordion animation when it gains focus. Otherwise,
diff --git a/src/com/android/camera/widget/SettingsCling.java b/src/com/android/camera/widget/SettingsCling.java
new file mode 100644
index 0000000..7ac42d4
--- /dev/null
+++ b/src/com/android/camera/widget/SettingsCling.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 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.camera.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.camera2.R;
+
+/**
+ * This is a cling widget for settings button. In addition to drawing a cling button
+ * background and overlaying text, it draws a small triangle that points at the
+ * settings button that this cling is for.
+ */
+public class SettingsCling extends FrameLayout {
+    private final int mClingTriangleHeight;
+    private final int mClingTriangleWidth;
+    private final Path mTrianglePath = new Path();
+    private final Paint mClingPaint = new Paint();
+
+    public SettingsCling(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setWillNotDraw(false);
+        mClingTriangleHeight = getResources().getDimensionPixelSize(
+                R.dimen.settings_cling_triangle_height);
+        mClingTriangleWidth = getResources().getDimensionPixelSize(
+                R.dimen.settings_cling_triangle_width);
+        mClingPaint.setColor(getResources().getColor(R.color.settings_cling_color));
+        mClingPaint.setStyle(Paint.Style.FILL);
+    }
+
+    /**
+     * Updates the current position of the cling based on a reference view. If there
+     * is enough space to lay out the cling on top of the reference view, then have
+     * the cling on top. Otherwise, position the cling underneath the reference view.
+     *
+     * @param referenceView a view that cling uses as a position reference
+     */
+    public void updatePosition(View referenceView) {
+        if (referenceView == null) {
+            return;
+        }
+        // Right align cling:
+        float referenceRight = referenceView.getX() + referenceView.getMeasuredWidth();
+        setTranslationX(referenceRight - getMeasuredWidth());
+
+        float referenceTop = referenceView.getY();
+        if (referenceTop < getMeasuredHeight()) {
+            // Layout cling under reference view.
+            setTranslationY(referenceTop + referenceView.getMeasuredHeight());
+            float triangleStartX = getMeasuredWidth() - referenceView.getMeasuredWidth() / 2;
+            float triangleStartY = 0;
+            mTrianglePath.reset();
+            mTrianglePath.moveTo(triangleStartX, triangleStartY);
+            mTrianglePath.lineTo(triangleStartX - mClingTriangleWidth / 2,
+                    triangleStartY + mClingTriangleHeight);
+            mTrianglePath.lineTo(triangleStartX + mClingTriangleWidth / 2,
+                    triangleStartY + mClingTriangleHeight);
+            mTrianglePath.lineTo(triangleStartX, triangleStartY);
+        } else {
+            // Layout cling on top of reference view.
+            setTranslationY(referenceTop - getMeasuredHeight());
+            float triangleStartX = getMeasuredWidth() - referenceView.getMeasuredWidth() / 2;
+            float triangleStartY = getMeasuredHeight();
+            mTrianglePath.reset();
+            mTrianglePath.moveTo(triangleStartX, triangleStartY);
+            mTrianglePath.lineTo(triangleStartX - mClingTriangleWidth / 2,
+                    triangleStartY - mClingTriangleHeight);
+            mTrianglePath.lineTo(triangleStartX + mClingTriangleWidth / 2,
+                    triangleStartY - mClingTriangleHeight);
+            mTrianglePath.lineTo(triangleStartX, triangleStartY);
+        }
+        invalidate();
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        // Draw triangle.
+        canvas.drawPath(mTrianglePath, mClingPaint);
+    }
+}