diff options
Diffstat (limited to 'apps/NotificationStudio')
45 files changed, 2341 insertions, 0 deletions
diff --git a/apps/NotificationStudio/.classpath b/apps/NotificationStudio/.classpath new file mode 100644 index 000000000..a4763d1ee --- /dev/null +++ b/apps/NotificationStudio/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/apps/NotificationStudio/.project b/apps/NotificationStudio/.project new file mode 100644 index 000000000..00f0a2118 --- /dev/null +++ b/apps/NotificationStudio/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>NotificationStudio</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/apps/NotificationStudio/.settings/org.eclipse.jdt.core.prefs b/apps/NotificationStudio/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f77b31c2d --- /dev/null +++ b/apps/NotificationStudio/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/apps/NotificationStudio/AndroidManifest.xml b/apps/NotificationStudio/AndroidManifest.xml new file mode 100644 index 000000000..cb849e006 --- /dev/null +++ b/apps/NotificationStudio/AndroidManifest.xml @@ -0,0 +1,38 @@ +<!-- + Copyright 2012 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.notificationstudio" + android:versionCode="5" + android:versionName="0.5" > + + <uses-sdk android:targetSdkVersion="16" android:minSdkVersion="10" /> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + + <application android:label="@string/app_name" > + <activity + android:name=".NotificationStudioActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest>
\ No newline at end of file diff --git a/apps/NotificationStudio/libs/android-support-v4.jar b/apps/NotificationStudio/libs/android-support-v4.jar Binary files differnew file mode 100644 index 000000000..f92dea2aa --- /dev/null +++ b/apps/NotificationStudio/libs/android-support-v4.jar diff --git a/apps/NotificationStudio/project.properties b/apps/NotificationStudio/project.properties new file mode 100644 index 000000000..9b84a6b4b --- /dev/null +++ b/apps/NotificationStudio/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 diff --git a/apps/NotificationStudio/res/drawable-hdpi/android_logo.gif b/apps/NotificationStudio/res/drawable-hdpi/android_logo.gif Binary files differnew file mode 100644 index 000000000..6078e8632 --- /dev/null +++ b/apps/NotificationStudio/res/drawable-hdpi/android_logo.gif diff --git a/apps/NotificationStudio/res/drawable-hdpi/ic_notification_multiple_mail_holo_dark.png b/apps/NotificationStudio/res/drawable-hdpi/ic_notification_multiple_mail_holo_dark.png Binary files differnew file mode 100644 index 000000000..c4f3648c2 --- /dev/null +++ b/apps/NotificationStudio/res/drawable-hdpi/ic_notification_multiple_mail_holo_dark.png diff --git a/apps/NotificationStudio/res/drawable-hdpi/romain.jpg b/apps/NotificationStudio/res/drawable-hdpi/romain.jpg Binary files differnew file mode 100644 index 000000000..e93290199 --- /dev/null +++ b/apps/NotificationStudio/res/drawable-hdpi/romain.jpg diff --git a/apps/NotificationStudio/res/drawable-nodpi/icon_bg.xml b/apps/NotificationStudio/res/drawable-nodpi/icon_bg.xml new file mode 100644 index 000000000..dcecdd3d2 --- /dev/null +++ b/apps/NotificationStudio/res/drawable-nodpi/icon_bg.xml @@ -0,0 +1,29 @@ +<!-- + Copyright 2012 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_selected="true"> + <shape android:shape="rectangle"> + <solid android:color="@color/icon_background" /> + <stroke android:width="1px" android:color="@android:color/holo_blue_light" /> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <solid android:color="@color/icon_background" /> + </shape> + </item> +</selector>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/drawable-nodpi/romainguy_rockaway.jpg b/apps/NotificationStudio/res/drawable-nodpi/romainguy_rockaway.jpg Binary files differnew file mode 100644 index 000000000..68473ba6c --- /dev/null +++ b/apps/NotificationStudio/res/drawable-nodpi/romainguy_rockaway.jpg diff --git a/apps/NotificationStudio/res/layout-v14/boolean_editor.xml b/apps/NotificationStudio/res/layout-v14/boolean_editor.xml new file mode 100644 index 000000000..ae7746852 --- /dev/null +++ b/apps/NotificationStudio/res/layout-v14/boolean_editor.xml @@ -0,0 +1,21 @@ +<!-- + Copyright 2012 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. + --> + + <Switch xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> diff --git a/apps/NotificationStudio/res/layout-v16/studio.xml b/apps/NotificationStudio/res/layout-v16/studio.xml new file mode 100644 index 000000000..083ac7970 --- /dev/null +++ b/apps/NotificationStudio/res/layout-v16/studio.xml @@ -0,0 +1,33 @@ +<!-- + Copyright 2012 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. + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <com.android.notificationstudio.MaxHeightScrollView + android:id="@+id/preview_scroller" + android:layout_width="@dimen/notification_panel_width" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="5dp" > + + <include layout="@layout/preview" /> + </com.android.notificationstudio.MaxHeightScrollView> + + <include layout="@layout/editors" /> + +</FrameLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout-w801dp/studio.xml b/apps/NotificationStudio/res/layout-w801dp/studio.xml new file mode 100644 index 000000000..0391f8ba0 --- /dev/null +++ b/apps/NotificationStudio/res/layout-w801dp/studio.xml @@ -0,0 +1,28 @@ +<!-- + Copyright 2012 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" > + + <include + android:layout_width="@dimen/notification_panel_width" + android:layout_height="match_parent" + layout="@layout/preview" /> + + <include layout="@layout/editors" /> + +</LinearLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout/boolean_editor.xml b/apps/NotificationStudio/res/layout/boolean_editor.xml new file mode 100644 index 000000000..e4823221b --- /dev/null +++ b/apps/NotificationStudio/res/layout/boolean_editor.xml @@ -0,0 +1,20 @@ +<!-- + Copyright 2012 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. + --> + +<View xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> diff --git a/apps/NotificationStudio/res/layout/divider.xml b/apps/NotificationStudio/res/layout/divider.xml new file mode 100644 index 000000000..d2e20f8a5 --- /dev/null +++ b/apps/NotificationStudio/res/layout/divider.xml @@ -0,0 +1,40 @@ +<!-- + Copyright 2012 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="wrap_content" + android:orientation="vertical" > + + <TextView + android:id="@+id/divider_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/editor_inset" + android:layout_marginTop="3dp" + android:textAllCaps="true" + android:textColor="@color/divider_text" + android:textSize="@dimen/editor_text_size" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_marginLeft="@dimen/editor_inset" + android:layout_marginRight="@dimen/editor_inset" + android:layout_marginTop="3dp" + android:background="@color/divider_text" /> + +</LinearLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout/editable_item.xml b/apps/NotificationStudio/res/layout/editable_item.xml new file mode 100644 index 000000000..816dd0f9a --- /dev/null +++ b/apps/NotificationStudio/res/layout/editable_item.xml @@ -0,0 +1,111 @@ +<!-- + Copyright 2012 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" + android:id="@+id/list_item_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="@dimen/editor_inset" > + + <TextView + android:id="@+id/caption" + android:layout_width="@dimen/editor_caption_width" + android:layout_height="wrap_content" + android:paddingBottom="@dimen/caption_padding_bottom" + android:paddingTop="@dimen/caption_padding_top" + android:textSize="@dimen/editor_text_size" /> + + <EditText + android:id="@+id/text_editor" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/caption" + android:imeOptions="actionDone" + android:inputType="text" + android:paddingTop="0dp" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> + + <View + android:layout_width="0px" + android:layout_height="0px" + android:focusable="true" + android:focusableInTouchMode="true" /> + + <ViewStub + android:id="@+id/boolean_editor_stub" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/caption" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> + + <Spinner + android:id="@+id/drop_down_editor" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/caption" + android:focusable="true" + android:focusableInTouchMode="true" + android:visibility="gone" /> + + <HorizontalScrollView + android:id="@+id/icon_editor_scroller" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/caption" + android:scrollbars="none" + android:visibility="gone" > + + <LinearLayout + android:id="@+id/icon_editor_layout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + </LinearLayout> + </HorizontalScrollView> + + <Button + android:id="@+id/date_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/caption" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> + + <Button + android:id="@+id/time_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/date_button" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> + + <Button + android:id="@+id/reset_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBaseline="@id/caption" + android:layout_toRightOf="@id/time_button" + android:text="@string/now" + android:textSize="@dimen/editor_text_size" + android:visibility="gone" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout/editors.xml b/apps/NotificationStudio/res/layout/editors.xml new file mode 100644 index 000000000..7c7e12009 --- /dev/null +++ b/apps/NotificationStudio/res/layout/editors.xml @@ -0,0 +1,29 @@ +<!-- + Copyright 2012 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. + --> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/editors" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@android:color/black" > + + <LinearLayout + android:id="@+id/items" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" /> + +</ScrollView>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout/preview.xml b/apps/NotificationStudio/res/layout/preview.xml new file mode 100644 index 000000000..3d9c7a082 --- /dev/null +++ b/apps/NotificationStudio/res/layout/preview.xml @@ -0,0 +1,56 @@ +<!-- + Copyright 2012 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/preview" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + <FrameLayout + android:id="@+id/ticker" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> + + <ImageView + android:id="@+id/large_icon" + android:layout_width="@android:dimen/notification_large_icon_width" + android:layout_height="@android:dimen/notification_large_icon_height" + android:layout_alignParentLeft="true" + android:layout_below="@id/ticker" + android:scaleType="center" + android:visibility="gone" + tools:ignore="ContentDescription" /> + + <FrameLayout + android:id="@+id/oneU" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/ticker" + android:layout_marginTop="5dp" + android:layout_toRightOf="@id/large_icon" + android:visibility="gone" /> + + <FrameLayout + android:id="@+id/fourU" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/oneU" + android:layout_marginTop="5dp" + android:visibility="gone" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/layout/studio.xml b/apps/NotificationStudio/res/layout/studio.xml new file mode 100644 index 000000000..2646a44d3 --- /dev/null +++ b/apps/NotificationStudio/res/layout/studio.xml @@ -0,0 +1,26 @@ +<!-- + Copyright 2012 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" > + + <include layout="@layout/preview" /> + + <include layout="@layout/editors" /> + +</LinearLayout>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/menu/action_bar.xml b/apps/NotificationStudio/res/menu/action_bar.xml new file mode 100644 index 000000000..35c897fe6 --- /dev/null +++ b/apps/NotificationStudio/res/menu/action_bar.xml @@ -0,0 +1,30 @@ +<!-- + Copyright 2012 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" > + + <item + android:id="@+id/action_share_code" + android:icon="@android:drawable/ic_menu_share" + android:showAsAction="never" + android:title="@string/share_generated_code"/> + <item + android:id="@+id/action_share_mockup" + android:icon="@android:drawable/ic_menu_share" + android:showAsAction="never" + android:title="@string/share_mockup"/> + +</menu>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values-sw600dp/dimens.xml b/apps/NotificationStudio/res/values-sw600dp/dimens.xml new file mode 100644 index 000000000..22e863f3c --- /dev/null +++ b/apps/NotificationStudio/res/values-sw600dp/dimens.xml @@ -0,0 +1,24 @@ +<!-- + Copyright 2012 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. + --> + +<resources> + + <dimen name="notification_panel_width">446dp</dimen> + <dimen name="caption_padding_bottom">6dp</dimen> + <dimen name="editor_text_size">16dp</dimen> + <dimen name="editor_caption_width">110dp</dimen> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values-sw720dp/dimens.xml b/apps/NotificationStudio/res/values-sw720dp/dimens.xml new file mode 100644 index 000000000..f8960473d --- /dev/null +++ b/apps/NotificationStudio/res/values-sw720dp/dimens.xml @@ -0,0 +1,21 @@ +<!-- + Copyright 2012 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. + --> + +<resources> + + <dimen name="notification_panel_width">448dp</dimen> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values-v11/colors.xml b/apps/NotificationStudio/res/values-v11/colors.xml new file mode 100644 index 000000000..224b09e70 --- /dev/null +++ b/apps/NotificationStudio/res/values-v11/colors.xml @@ -0,0 +1,21 @@ +<!-- + Copyright 2012 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. +--> + +<resources> + + <color name="divider_text">@android:color/holo_blue_bright</color> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values-v11/dimens.xml b/apps/NotificationStudio/res/values-v11/dimens.xml new file mode 100644 index 000000000..f5fd098fb --- /dev/null +++ b/apps/NotificationStudio/res/values-v11/dimens.xml @@ -0,0 +1,21 @@ +<!-- + Copyright 2012 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. +--> + +<resources> + + <dimen name="caption_padding_top">6dp</dimen> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values/colors.xml b/apps/NotificationStudio/res/values/colors.xml new file mode 100644 index 000000000..aabe9bc25 --- /dev/null +++ b/apps/NotificationStudio/res/values/colors.xml @@ -0,0 +1,23 @@ +<!-- + Copyright 2012 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. +--> + +<resources> + + <color name="gb_background">#dddddd</color> + <color name="divider_text">#dddddd</color> + <color name="icon_background">#3333B5E5</color> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values/dimens.xml b/apps/NotificationStudio/res/values/dimens.xml new file mode 100644 index 000000000..e960ae6f6 --- /dev/null +++ b/apps/NotificationStudio/res/values/dimens.xml @@ -0,0 +1,33 @@ +<!-- + Copyright 2012 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. + --> + +<resources> + + <dimen name="notification_panel_width">-1dp</dimen> <!-- MATCH_PARENT --> + <dimen name="editor_inset">8dp</dimen> + <dimen name="caption_padding_top">10dp</dimen> + <dimen name="caption_padding_bottom">0dp</dimen> + <dimen name="editor_text_size">12dp</dimen> + <dimen name="editor_caption_width">95dp</dimen> + <dimen name="editor_icon_size_small">40dp</dimen> + <dimen name="editor_icon_size_large">60dp</dimen> + <dimen name="editor_icon_outer_margin">5dp</dimen> + <dimen name="editor_icon_inner_margin">2dp</dimen> + <dimen name="editor_drop_down_padding">5dp</dimen> + <dimen name="editor_datetime_padding_v">0dp</dimen> + <dimen name="editor_datetime_padding_h">15dp</dimen> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/res/values/strings.xml b/apps/NotificationStudio/res/values/strings.xml new file mode 100644 index 000000000..e3990f3d9 --- /dev/null +++ b/apps/NotificationStudio/res/values/strings.xml @@ -0,0 +1,55 @@ +<!-- + Copyright 2012 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. +--> + +<resources> + + <string name="app_name">Notification Studio</string> + <string name="now">Now</string> + <string name="share_generated_code">Share generated code…</string> + <string name="share_mockup">Share mockup…</string> + <string name="preset">Preset</string> + <string name="small_icon">Small Icon</string> + <string name="content_title">Content Title</string> + <string name="content_text">Content Text</string> + <string name="sub_text">Sub Text</string> + <string name="large_icon">Large Icon</string> + <string name="content_info">Content Info</string> + <string name="number">Number</string> + <string name="when">When</string> + <string name="progress">Progress</string> + <string name="uses_chron">Uses Chron</string> + <string name="style">Style</string> + <string name="picture">Picture</string> + <string name="big_text">Big Text</string> + <string name="lines">Lines</string> + <string name="big_content_title">Big Content Title</string> + <string name="summary_text">Summary Text</string> + <string name="icon">Icon</string> + <string name="text">Text</string> + <string name="properties">Properties</string> + <string name="action_1">Action 1</string> + <string name="action_2">Action 2</string> + <string name="action_3">Action 3</string> + <string name="preset_custom">(custom)</string> + <string name="preset_basic">Basic example</string> + <string name="preset_email">Email example</string> + <string name="preset_photo">Photo example</string> + <string name="style_none">(none)</string> + <string name="style_big_picture">BigPictureStyle</string> + <string name="style_big_text">BigTextStyle</string> + <string name="style_inbox">InboxStyle</string> + +</resources>
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/MaxHeightScrollView.java b/apps/NotificationStudio/src/com/android/notificationstudio/MaxHeightScrollView.java new file mode 100644 index 000000000..1fc0284b1 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/MaxHeightScrollView.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012 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.notificationstudio; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ScrollView; + +public class MaxHeightScrollView extends ScrollView { + + private int mMaxHeight; + + public MaxHeightScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setMaxHeight(int maxHeight) { + mMaxHeight = maxHeight; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(getMeasuredWidth(), Math.min(getMeasuredHeight(), mMaxHeight)); + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/NotificationStudioActivity.java b/apps/NotificationStudio/src/com/android/notificationstudio/NotificationStudioActivity.java new file mode 100644 index 000000000..9c2e8119a --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/NotificationStudioActivity.java @@ -0,0 +1,249 @@ +/* + * Copyright 2012 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.notificationstudio; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnLayoutChangeListener; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.FrameLayout.LayoutParams; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RemoteViews; +import android.widget.TextView; + +import com.android.notificationstudio.action.ShareCodeAction; +import com.android.notificationstudio.action.ShareMockupAction; +import com.android.notificationstudio.editor.Editors; +import com.android.notificationstudio.generator.NotificationGenerator; +import com.android.notificationstudio.model.EditableItem; +import com.android.notificationstudio.model.EditableItemConstants; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class NotificationStudioActivity extends Activity implements EditableItemConstants{ + private static final String TAG = NotificationStudioActivity.class.getSimpleName(); + private static final int PREVIEW_NOTIFICATION = 1; + private static final int REFRESH_DELAY = 50; + private static final ExecutorService BACKGROUND = Executors.newSingleThreadExecutor(); + + private boolean mRefreshPending; + + private final Handler mHandler = new Handler(); + private final Runnable mRefreshNotificationInner = new Runnable() { + public void run() { + refreshNotificationInner(); + }}; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getWindow().setBackgroundDrawableResource(android.R.color.black); + setContentView(R.layout.studio); + initPreviewScroller(); + + EditableItem.initIfNecessary(this); + + initEditors(); + } + + private void initPreviewScroller() { + + MaxHeightScrollView preview = (MaxHeightScrollView) findViewById(R.id.preview_scroller); + if (preview == null) + return; + final int margin = ((ViewGroup.MarginLayoutParams) preview.getLayoutParams()).bottomMargin; + preview.addOnLayoutChangeListener(new OnLayoutChangeListener(){ + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + // animate preview height changes + if (oldBottom != bottom) { + final View e = findViewById(R.id.editors); + final int y = bottom + margin; + e.animate() + .translationY(y - oldBottom) + .setListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + FrameLayout.LayoutParams lp = (LayoutParams) e.getLayoutParams(); + lp.topMargin = y; + e.setTranslationY(0); + e.setLayoutParams(lp); + } + }); + } + }}); + + // limit the max height for preview, leave room for editors + soft keyboard + DisplayMetrics dm = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(dm); + float actualHeight = dm.heightPixels / dm.ydpi; + float pct = actualHeight < 3.5 ? .32f : + actualHeight < 4 ? .35f : + .38f; + preview.setMaxHeight((int)(dm.heightPixels * pct)); + } + + private void initEditors() { + LinearLayout items = (LinearLayout) findViewById(R.id.items); + items.removeAllViews(); + String currentCategory = null; + for (EditableItem item : EditableItem.values()) { + String itemCategory = item.getCategory(this); + if (!itemCategory.equals(currentCategory)) { + View dividerView = getLayoutInflater().inflate(R.layout.divider, null); + ((TextView) dividerView.findViewById(R.id.divider_text)).setText(itemCategory); + items.addView(dividerView); + currentCategory = itemCategory; + } + View editorView = Editors.newEditor(this, items, item); + if (editorView != null) + items.addView(editorView); + } + refreshNotification(); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + // we'll take care of restoring state + } + + public void refreshNotification() { + mRefreshPending = true; + mHandler.postDelayed(mRefreshNotificationInner, REFRESH_DELAY); + } + + private void refreshNotificationInner() { + if (!mRefreshPending) { + return; + } + final Notification notification = NotificationGenerator.build(this); + ViewGroup oneU = (ViewGroup) findViewById(R.id.oneU); + ViewGroup fourU = (ViewGroup) findViewById(R.id.fourU); + View oneUView = refreshRemoteViews(oneU, notification.contentView); + if (Build.VERSION.SDK_INT >= 16) + refreshRemoteViews(fourU, notification.bigContentView); + else if (Build.VERSION.SDK_INT >= 11) { + ImageView largeIcon = (ImageView) findViewById(R.id.large_icon); + largeIcon.setVisibility(notification.largeIcon == null ? View.GONE : View.VISIBLE); + if (notification.largeIcon != null) + largeIcon.setImageBitmap(notification.largeIcon); + } else if (oneUView != null) { + oneUView.setBackgroundColor(getResources().getColor(R.color.gb_background)); + oneUView.setMinimumHeight(100); + } + mRefreshPending = false; + + // this can take a while, run on a background thread + BACKGROUND.submit(new Runnable() { + public void run() { + NotificationManager mgr = + (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + try { + mgr.notify(PREVIEW_NOTIFICATION, notification); + } catch (Throwable t) { + Log.w(TAG, "Error displaying notification", t); + } + }}); + } + + private View refreshRemoteViews(ViewGroup parent, RemoteViews remoteViews) { + parent.removeAllViews(); + if (remoteViews != null) { + parent.setVisibility(View.VISIBLE); + try { + View v = remoteViews.apply(this, parent); + parent.addView(v); + return v; + } catch (Exception e) { + TextView exceptionView = new TextView(this); + exceptionView.setText(e.getClass().getSimpleName() + ": " + e.getMessage()); + parent.addView(exceptionView); + return exceptionView; + } + } else { + parent.setVisibility(View.GONE); + return null; + } + } + + // action bar setup + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.action_bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_share_code: + ShareCodeAction.launch(this, item.getTitle()); + return true; + case R.id.action_share_mockup: + ShareMockupAction.launch(this, item.getTitle()); + return true; + } + return false; + } + + // hides the soft keyboard more aggressively when leaving text editors + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + View v = getCurrentFocus(); + boolean ret = super.dispatchTouchEvent(event); + + if (v instanceof EditText) { + View currentFocus = getCurrentFocus(); + int screenCoords[] = new int[2]; + currentFocus.getLocationOnScreen(screenCoords); + float x = event.getRawX() + currentFocus.getLeft() - screenCoords[0]; + float y = event.getRawY() + currentFocus.getTop() - screenCoords[1]; + + if (event.getAction() == MotionEvent.ACTION_UP + && (x < currentFocus.getLeft() || + x >= currentFocus.getRight() || + y < currentFocus.getTop() || + y > currentFocus.getBottom())) { + InputMethodManager imm = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0); + } + } + return ret; + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareCodeAction.java b/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareCodeAction.java new file mode 100644 index 000000000..d7da43446 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareCodeAction.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012 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.notificationstudio.action; + +import android.content.Context; +import android.content.Intent; + +import com.android.notificationstudio.generator.CodeGenerator; + +public class ShareCodeAction { + + public static void launch(Context context, CharSequence title) { + String shareBody = CodeGenerator.generate(context); + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Notification Code"); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody); + context.startActivity(Intent.createChooser(sharingIntent, title)); + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareMockupAction.java b/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareMockupAction.java new file mode 100644 index 000000000..e377475c1 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/action/ShareMockupAction.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012 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.notificationstudio.action; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.net.Uri; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import com.android.notificationstudio.R; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class ShareMockupAction { + private static final String TAG = ShareMockupAction.class.getSimpleName(); + + private static final SimpleDateFormat FILE_NAME = + new SimpleDateFormat("'notification.'yyyyMMdd'.'HHmmss'.png'"); + + public static void launch(Activity activity, CharSequence title) { + // take a picture of the current mockup + View v = activity.findViewById(R.id.preview); + int w = v.getMeasuredWidth(); + int h = v.getMeasuredHeight(); + Bitmap mockup = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(mockup); + v.layout(0, 0, w, h); + v.draw(c); + + // write the mockup to a temp file + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + mockup.compress(Bitmap.CompressFormat.PNG, 100, bytes); + File f = new File(activity.getExternalCacheDir(), FILE_NAME.format(new Date())); + FileOutputStream fo = null; + try { + f.createNewFile(); + fo = new FileOutputStream(f); + fo.write(bytes.toByteArray()); + } catch (IOException e) { + String msg = "Error writing mockup file"; + Log.w(TAG, msg, e); + Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show(); + return; + } finally { + if (fo != null) + try { fo.close(); } catch (Exception e) { } + } + + // launch intent to send the mockup image + Intent share = new Intent(Intent.ACTION_SEND); + share.setType("image/png"); + share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f.getAbsoluteFile())); + activity.startActivity(Intent.createChooser(share, title)); + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/BitmapEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/BitmapEditor.java new file mode 100644 index 000000000..04194acc3 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/BitmapEditor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import com.android.notificationstudio.R; + +public class BitmapEditor extends IconEditor { + + @Override + protected void setImage(ImageView imageView, Object value) { + imageView.setImageBitmap((Bitmap) value); + } + + protected int getIconSize(Resources res) { + return res.getDimensionPixelSize(R.dimen.editor_icon_size_large); + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/BooleanEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/BooleanEditor.java new file mode 100644 index 000000000..6a6a8cfbd --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/BooleanEditor.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.view.View; +import android.view.ViewStub; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.Switch; + +import com.android.notificationstudio.R; +import com.android.notificationstudio.editor.Editors.Editor; +import com.android.notificationstudio.model.EditableItem; + +public class BooleanEditor implements Editor { + + public Runnable bindEditor(View v, final EditableItem item, final Runnable afterChange) { + final ViewStub booleanEditorStub = (ViewStub) v.findViewById(R.id.boolean_editor_stub); + booleanEditorStub.setLayoutResource(R.layout.boolean_editor); + final Switch booleanEditor = (Switch) booleanEditorStub.inflate(); + Runnable updateSwitch = new Runnable() { + public void run() { + booleanEditor.setChecked(item.hasValue() && item.getValueBool()); + }}; + booleanEditor.setVisibility(View.VISIBLE); + updateSwitch.run(); + booleanEditor.setOnCheckedChangeListener(new OnCheckedChangeListener(){ + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + item.setValue(isChecked); + afterChange.run(); + }}); + return updateSwitch; + } + +}
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/DateTimeEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/DateTimeEditor.java new file mode 100644 index 000000000..8089de139 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/DateTimeEditor.java @@ -0,0 +1,139 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.app.DatePickerDialog.OnDateSetListener; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.FragmentTransaction; +import android.app.TimePickerDialog; +import android.app.TimePickerDialog.OnTimeSetListener; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.TimePicker; + +import com.android.notificationstudio.R; +import com.android.notificationstudio.editor.Editors.Editor; +import com.android.notificationstudio.model.EditableItem; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateTimeEditor implements Editor { + private static final SimpleDateFormat YYYY_MM_DD = new SimpleDateFormat("yyyy/MM/dd"); + private static final SimpleDateFormat HH_MM_SS = new SimpleDateFormat("HH:mm:ss"); + + @SuppressWarnings("deprecation") + public Runnable bindEditor(View v, final EditableItem item, final Runnable afterChange) { + + final Button dateButton = (Button) v.findViewById(R.id.date_button); + final Button timeButton = (Button) v.findViewById(R.id.time_button); + final Button resetButton = (Button) v.findViewById(R.id.reset_button); + + int vPad = v.getResources().getDimensionPixelSize(R.dimen.editor_datetime_padding_v); + int hPad = v.getResources().getDimensionPixelSize(R.dimen.editor_datetime_padding_h); + for (Button b : new Button[] { dateButton, timeButton, resetButton }) { + b.setVisibility(View.VISIBLE); + b.setPadding(hPad, vPad, hPad, vPad); + } + + final Runnable updateButtonText = new Runnable() { + public void run() { + Date d = getDateTime(item); + String dateString = YYYY_MM_DD.format(d); + dateButton.setText(dateString); + String timeString = HH_MM_SS.format(d); + timeButton.setText(timeString); + }}; + updateButtonText.run(); + + // wire up date button + DialogFragment datePickerFragment = new DialogFragment() { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Date d = getDateTime(item); + OnDateSetListener onDateSet = new OnDateSetListener() { + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + Date d = getDateTime(item); + d.setYear(year - 1900); + d.setMonth(monthOfYear); + d.setDate(dayOfMonth); + item.setValue(d.getTime()); + updateButtonText.run(); + afterChange.run(); + } + }; + return new DatePickerDialog(getActivity(), onDateSet, + d.getYear() + 1900, d.getMonth(), d.getDate()); + } + }; + Activity activity = (Activity) v.getContext(); + launchDialogOnClick(activity, "datePicker", dateButton, datePickerFragment); + + // wire up time button + DialogFragment timePickerFragment = new DialogFragment() { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Date d = getDateTime(item); + OnTimeSetListener onTimeSet = new OnTimeSetListener() { + public void onTimeSet(TimePicker view, int hourOfDay, + int minute) { + Date d = getDateTime(item); + d.setHours(hourOfDay); + d.setMinutes(minute); + item.setValue(d.getTime()); + updateButtonText.run(); + afterChange.run(); + } + }; + return new TimePickerDialog(getActivity(), + onTimeSet, d.getHours(), d.getMinutes(), true); + } + }; + launchDialogOnClick(activity, "timePicker", timeButton, timePickerFragment); + + // wire up reset button + resetButton.setOnClickListener(new OnClickListener(){ + public void onClick(View v) { + item.setValue(null); + updateButtonText.run(); + afterChange.run(); + }}); + return updateButtonText; + } + + private static Date getDateTime(EditableItem item) { + long value = item.hasValue() ? item.getValueLong() : System.currentTimeMillis(); + return new Date(value); + } + + private static void launchDialogOnClick(final Activity activity, + final String tag, Button button, final DialogFragment fragment) { + button.setOnClickListener(new OnClickListener(){ + public void onClick(View v) { + FragmentTransaction ft = activity.getFragmentManager().beginTransaction(); + fragment.show(ft, tag); + }}); + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/DropDownEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/DropDownEditor.java new file mode 100644 index 000000000..64490fafe --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/DropDownEditor.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import android.widget.TextView; + +import com.android.notificationstudio.R; +import com.android.notificationstudio.editor.Editors.Editor; +import com.android.notificationstudio.model.EditableItem; + +public class DropDownEditor implements Editor { + + public Runnable bindEditor(View v, final EditableItem item, final Runnable afterChange) { + final Spinner dropDownEditor = (Spinner) v.findViewById(R.id.drop_down_editor); + dropDownEditor.setVisibility(View.VISIBLE); + Integer[] values = item.getAvailableValuesInteger(); + final float textSize = v.getResources().getDimensionPixelSize(R.dimen.editor_text_size); + final int p = v.getResources().getDimensionPixelSize(R.dimen.editor_drop_down_padding); + final int p2 = p * 2; + final ArrayAdapter<Integer> adapter = + new ArrayAdapter<Integer>(v.getContext(), android.R.layout.simple_spinner_item, values) { + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + TextView v = (TextView) super.getDropDownView(position, convertView, parent); + v.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + v.setPadding(p2, p2, p2, p2); + v.setText(v.getResources().getString(getItem(position))); + return v; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + TextView v = (TextView) super.getView(position, convertView, parent); + v.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + v.setPadding(p, p, p, p); + v.setText(v.getResources().getString(getItem(position))); + return v; + } + }; + dropDownEditor.setAdapter(adapter); + Runnable updateSelection = new Runnable() { + public void run() { + dropDownEditor.setSelection(adapter.getPosition(item.getValueInt())); + }}; + if (item.hasValue()) + updateSelection.run(); + dropDownEditor.setOnItemSelectedListener(new OnItemSelectedListener(){ + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + Object oldValue = item.getValue(); + Object newValue = adapter.getItem(position); + if (newValue.equals(oldValue)) + return; + item.setValue(newValue); + afterChange.run(); + } + public void onNothingSelected(AdapterView<?> parent) { + // noop + }}); + return updateSelection; + } + +}
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/Editors.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/Editors.java new file mode 100644 index 000000000..b7268f111 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/Editors.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.android.notificationstudio.NotificationStudioActivity; +import com.android.notificationstudio.R; +import com.android.notificationstudio.model.EditableItem; +import com.android.notificationstudio.model.EditableItemConstants; + +import java.util.HashMap; +import java.util.Map; + +public class Editors implements EditableItemConstants { + + public interface Editor { + Runnable bindEditor(View v, EditableItem item, Runnable afterChange); + } + + private static final Map<Integer, Editor> EDITORS = editors(); + private static Runnable sUpdatePreset; + + private static Map<Integer, Editor> editors() { + Map<Integer, Editor> editors = new HashMap<Integer, Editor>(); + editors.put(TYPE_RESOURCE_ID, new IconEditor()); + editors.put(TYPE_TEXT, new TextEditor()); + editors.put(TYPE_INT, new IntEditor()); + if (Build.VERSION.SDK_INT >= 14) // switch 14, progress 14, uses chron 16 + editors.put(TYPE_BOOLEAN, new BooleanEditor()); + editors.put(TYPE_DROP_DOWN, new DropDownEditor()); + editors.put(TYPE_BITMAP, new BitmapEditor()); + if (Build.VERSION.SDK_INT >= 11) // fragments 11, when 11 + editors.put(TYPE_DATETIME, new DateTimeEditor()); + editors.put(TYPE_TEXT_LINES, new LinesEditor()); + return editors; + } + + public static View newEditor(final NotificationStudioActivity activity, + final ViewGroup parent, final EditableItem item) { + final View editorView = activity.getLayoutInflater().inflate(R.layout.editable_item, null); + ((TextView) editorView.findViewById(R.id.caption)).setText(item.getCaption(activity)); + + // bind visibility + editorView.setVisibility(item.isVisible() ? View.VISIBLE : View.GONE); + item.setVisibilityListener(new Runnable(){ + public void run() { + editorView.setVisibility(item.isVisible() ? View.VISIBLE : View.GONE); + }}); + + // bind type-specific behavior + Editor editor = EDITORS.get(item.getType()); + if (editor == null) + return null; + Runnable updater = editor.bindEditor(editorView, item, new Runnable() { + public void run() { + if (item.equals(EditableItem.PRESET)) { + updateEditors(parent); + } else { + EditableItem.PRESET.setValue(PRESET_CUSTOM); + sUpdatePreset.run(); + } + activity.refreshNotification(); + }}); + + // store the updater as the view tag + editorView.setTag(updater); + if (item.equals(EditableItem.PRESET)) + sUpdatePreset = updater; + + return editorView; + } + + private static void updateEditors(ViewGroup parent) { + for (int i = 0; i < parent.getChildCount(); i++) { + Object childTag = parent.getChildAt(i).getTag(); + if (childTag instanceof Runnable) { + ((Runnable) childTag).run(); + } + } + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/IconEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/IconEditor.java new file mode 100644 index 000000000..71e900567 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/IconEditor.java @@ -0,0 +1,118 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.content.res.Resources; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.View.OnTouchListener; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.LinearLayout; + +import com.android.notificationstudio.R; +import com.android.notificationstudio.editor.Editors.Editor; +import com.android.notificationstudio.model.EditableItem; + +public class IconEditor implements Editor { + + public Runnable bindEditor(View v, final EditableItem item, final Runnable afterChange) { + final LinearLayout iconEditor = (LinearLayout) v.findViewById(R.id.icon_editor_layout); + final HorizontalScrollView scroller = + (HorizontalScrollView) v.findViewById(R.id.icon_editor_scroller); + scroller.setVisibility(View.VISIBLE); + + final Object[] displayValues = getAvailableValuesForDisplay(item); + final Runnable updateSelection = new Runnable() { + public void run() { + for (int i=0;i<iconEditor.getChildCount();i++) { + View imageViewHolder = iconEditor.getChildAt(i); + Object iconResId = imageViewHolder.getTag(); + boolean selected = item.hasValue() && item.getValue().equals(iconResId) || + !item.hasValue() && iconResId == null; + imageViewHolder.setSelected(selected); + if (selected) { + int x = imageViewHolder.getLeft(); + if (x < scroller.getScrollX() || + x > scroller.getScrollX() + scroller.getWidth()) { + scroller.scrollTo(imageViewHolder.getLeft(), 0); + } + } + } + }}; + + int iconSize = getIconSize(v.getResources()); + int outerMargin = v.getResources().getDimensionPixelSize(R.dimen.editor_icon_outer_margin); + int innerMargin = v.getResources().getDimensionPixelSize(R.dimen.editor_icon_inner_margin); + + for (final Object iconResId : displayValues) { + final FrameLayout imageViewHolder = new FrameLayout(v.getContext()); + imageViewHolder.setTag(iconResId); + final ImageView imageView = new ImageView(v.getContext()); + imageView.setScaleType(ScaleType.CENTER); + imageView.setOnTouchListener(new OnTouchListener(){ + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + v.playSoundEffect(SoundEffectConstants.CLICK); + item.setValue(iconResId); + updateSelection.run(); + afterChange.run(); + } + return true; + }}); + + imageViewHolder.setBackgroundResource(R.drawable.icon_bg); + if (iconResId != null) + setImage(imageView, iconResId); + + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(iconSize, iconSize); + lp.bottomMargin = lp.topMargin = lp.leftMargin = lp.rightMargin = outerMargin; + imageViewHolder.setLayoutParams(lp); + + FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + flp.bottomMargin = flp.topMargin = flp.leftMargin = flp.rightMargin = innerMargin; + imageView.setLayoutParams(flp); + + imageViewHolder.addView(imageView); + iconEditor.addView(imageViewHolder); + } + updateSelection.run(); + return updateSelection; + } + + protected int getIconSize(Resources res) { + return res.getDimensionPixelSize(R.dimen.editor_icon_size_small); + } + + protected void setImage(ImageView imageView, Object value) { + imageView.setImageResource((Integer) value); + } + + private Object[] getAvailableValuesForDisplay(EditableItem item) { + Object[] avail = item.getAvailableValues(); + Object[] rt = new Object[avail.length + 1]; + System.arraycopy(avail, 0, rt, 1, avail.length); + return rt; + } + +}
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/IntEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/IntEditor.java new file mode 100644 index 000000000..393863eb1 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/IntEditor.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.text.InputType; + +public class IntEditor extends TextEditor { + + @Override + protected Object parseValue(String str) { + return str == null ? null : Integer.parseInt(str); + } + + protected int getInputType() { + return InputType.TYPE_CLASS_NUMBER; + } + +}
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/LinesEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/LinesEditor.java new file mode 100644 index 000000000..5173a992f --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/LinesEditor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.text.InputType; + +public class LinesEditor extends TextEditor { + + @Override + protected int getInputType() { + return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE; + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/editor/TextEditor.java b/apps/NotificationStudio/src/com/android/notificationstudio/editor/TextEditor.java new file mode 100644 index 000000000..aa38eec34 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/editor/TextEditor.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012 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.notificationstudio.editor; + +import android.text.Editable; +import android.text.InputType; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; + +import com.android.notificationstudio.R; +import com.android.notificationstudio.editor.Editors.Editor; +import com.android.notificationstudio.model.EditableItem; + +public class TextEditor implements Editor { + + public Runnable bindEditor(View v, final EditableItem item, final Runnable afterChange) { + final EditText textEditor = (EditText) v.findViewById(R.id.text_editor); + textEditor.setVisibility(View.VISIBLE); + textEditor.setInputType(getInputType()); + Runnable updateEditText = new Runnable() { + public void run() { + textEditor.setText(item.getValue() == null ? "" : item.getValue().toString()); + }}; + if (item.hasValue()) + updateEditText.run(); + textEditor.addTextChangedListener(new TextWatcher() { + public void afterTextChanged(Editable s) { + Object newVal = parseValue(s.length() == 0 ? null : s.toString()); + if (equal(newVal, item.getValue())) + return; + item.setValue(newVal); + afterChange.run(); + } + + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // noop + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + // noop + } + }); + return updateEditText; + } + + protected int getInputType() { + return InputType.TYPE_CLASS_TEXT; + } + + protected Object parseValue(String str) { + return str; + } + + private static boolean equal(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + +}
\ No newline at end of file diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/generator/CodeGenerator.java b/apps/NotificationStudio/src/com/android/notificationstudio/generator/CodeGenerator.java new file mode 100644 index 000000000..81eca8319 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/generator/CodeGenerator.java @@ -0,0 +1,139 @@ +/* + * Copyright 2012 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.notificationstudio.generator; +import static com.android.notificationstudio.model.EditableItem.ACTION1_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION1_TEXT; +import static com.android.notificationstudio.model.EditableItem.ACTION2_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION2_TEXT; +import static com.android.notificationstudio.model.EditableItem.ACTION3_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION3_TEXT; +import static com.android.notificationstudio.model.EditableItem.BIG_CONTENT_TITLE; +import static com.android.notificationstudio.model.EditableItem.BIG_TEXT; +import static com.android.notificationstudio.model.EditableItem.CONTENT_INFO; +import static com.android.notificationstudio.model.EditableItem.CONTENT_TEXT; +import static com.android.notificationstudio.model.EditableItem.CONTENT_TITLE; +import static com.android.notificationstudio.model.EditableItem.LARGE_ICON; +import static com.android.notificationstudio.model.EditableItem.LINES; +import static com.android.notificationstudio.model.EditableItem.NUMBER; +import static com.android.notificationstudio.model.EditableItem.PICTURE; +import static com.android.notificationstudio.model.EditableItem.PROGRESS; +import static com.android.notificationstudio.model.EditableItem.SMALL_ICON; +import static com.android.notificationstudio.model.EditableItem.STYLE; +import static com.android.notificationstudio.model.EditableItem.SUB_TEXT; +import static com.android.notificationstudio.model.EditableItem.SUMMARY_TEXT; +import static com.android.notificationstudio.model.EditableItem.USES_CHRON; +import static com.android.notificationstudio.model.EditableItem.WHEN; + +import android.content.Context; + +import com.android.notificationstudio.model.EditableItem; +import com.android.notificationstudio.model.EditableItemConstants; + +public class CodeGenerator implements EditableItemConstants { + + private static final String INDENT = "\n "; + private static final String STYLE_INDENT = INDENT + " "; + + public static String generate(Context context) { + + StringBuilder sb = new StringBuilder("new Notification.Builder(context)"); + + if (SMALL_ICON.hasValue()) + sb.append(INDENT + ".setSmallIcon(" + getResourceVar(context, SMALL_ICON) + ")"); + if (CONTENT_TITLE.hasValue()) + sb.append(INDENT + ".setContentTitle(" + quote(CONTENT_TITLE) + ")"); + if (CONTENT_TEXT.hasValue()) + sb.append(INDENT + ".setContentText(" + quote(CONTENT_TEXT) + ")"); + if (SUB_TEXT.hasValue()) + sb.append(INDENT + ".setSubText(" + quote(SUB_TEXT) + ")"); + if (LARGE_ICON.hasValue()) + sb.append(INDENT + ".setLargeIcon(largeIconBitmap)"); + if (CONTENT_INFO.hasValue()) + sb.append(INDENT + ".setContentInfo(" + quote(CONTENT_INFO) + ")"); + if (NUMBER.hasValue()) + sb.append(INDENT + ".setNumber(" + NUMBER.getValueInt() + ")"); + if (WHEN.hasValue()) + sb.append(INDENT + ".setWhen(" + WHEN.getValueLong() + ")"); + if (PROGRESS.hasValue() && PROGRESS.getValueBool()) + sb.append(INDENT + ".setProgress(0, 0, true)"); + if (USES_CHRON.hasValue()) + sb.append(INDENT + ".setUsesChronometer(" + USES_CHRON.getValueBool() + ")"); + if (ACTION1_ICON.hasValue()) + generateAction(sb, ACTION1_ICON, ACTION1_TEXT, "action1PendingIntent"); + if (ACTION2_ICON.hasValue()) + generateAction(sb, ACTION2_ICON, ACTION2_TEXT, "action2PendingIntent"); + if (ACTION3_ICON.hasValue()) + generateAction(sb, ACTION3_ICON, ACTION3_TEXT, "action3PendingIntent"); + + if (STYLE.hasValue()) + generateStyle(sb); + + sb.append(INDENT + ".build();"); + return sb.toString(); + } + + private static void generateStyle(StringBuilder sb) { + Integer styleValue = STYLE.getValueInt(); + if (STYLE_BIG_PICTURE.equals(styleValue)) { + sb.append(INDENT + ".setStyle(new Notification.BigPictureStyle()"); + if (PICTURE.hasValue()) + sb.append(STYLE_INDENT + ".bigPicture(pictureBitmap)"); + } + if (STYLE_BIG_TEXT.equals(styleValue)) { + sb.append(INDENT + ".setStyle(new Notification.BigTextStyle()"); + if (BIG_TEXT.hasValue()) + sb.append(STYLE_INDENT + ".bigText(" + quote(BIG_TEXT) + ")"); + } + if (STYLE_INBOX.equals(styleValue)) { + sb.append(INDENT + ".setStyle(new Notification.InboxStyle()"); + if (LINES.hasValue()) { + for (String line : LINES.getValueString().split("\\n")) { + sb.append(STYLE_INDENT + ".addLine(" + quote(line) + ")"); + } + } + } + if (BIG_CONTENT_TITLE.hasValue()) + sb.append(STYLE_INDENT + ".setBigContentTitle(" + quote(BIG_CONTENT_TITLE) + ")"); + if (SUMMARY_TEXT.hasValue()) + sb.append(STYLE_INDENT + ".setSummaryText(" + quote(SUMMARY_TEXT) + ")"); + + sb.append(")"); + } + + private static void generateAction(StringBuilder sb, + EditableItem icon, EditableItem text, String intentName) { + sb.append(INDENT + + ".addAction(" + icon.getValueInt() + ", " + quote(text) + ", " + intentName + ")"); + } + + private static String quote(EditableItem text) { + return quote(text.getValueString()); + } + + private static String quote(String text) { + return text != null ? "\"" + text.replace("\"", "\\\"") + "\"" : "null"; + } + + private static String getResourceVar(Context context, EditableItem item) { + int resId = item.getValueInt(); + String packageName = context.getResources().getResourcePackageName(resId); + String type = context.getResources().getResourceTypeName(resId); + String entryName = context.getResources().getResourceEntryName(resId); + return packageName + ".R." + type + "." + entryName; + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/generator/NotificationGenerator.java b/apps/NotificationStudio/src/com/android/notificationstudio/generator/NotificationGenerator.java new file mode 100644 index 000000000..64b4ece28 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/generator/NotificationGenerator.java @@ -0,0 +1,131 @@ +/* + * Copyright 2012 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.notificationstudio.generator; +import static com.android.notificationstudio.model.EditableItem.ACTION1_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION1_TEXT; +import static com.android.notificationstudio.model.EditableItem.ACTION2_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION2_TEXT; +import static com.android.notificationstudio.model.EditableItem.ACTION3_ICON; +import static com.android.notificationstudio.model.EditableItem.ACTION3_TEXT; +import static com.android.notificationstudio.model.EditableItem.BIG_CONTENT_TITLE; +import static com.android.notificationstudio.model.EditableItem.BIG_TEXT; +import static com.android.notificationstudio.model.EditableItem.CONTENT_INFO; +import static com.android.notificationstudio.model.EditableItem.CONTENT_TEXT; +import static com.android.notificationstudio.model.EditableItem.CONTENT_TITLE; +import static com.android.notificationstudio.model.EditableItem.LARGE_ICON; +import static com.android.notificationstudio.model.EditableItem.LINES; +import static com.android.notificationstudio.model.EditableItem.NUMBER; +import static com.android.notificationstudio.model.EditableItem.PICTURE; +import static com.android.notificationstudio.model.EditableItem.PROGRESS; +import static com.android.notificationstudio.model.EditableItem.SMALL_ICON; +import static com.android.notificationstudio.model.EditableItem.STYLE; +import static com.android.notificationstudio.model.EditableItem.SUB_TEXT; +import static com.android.notificationstudio.model.EditableItem.SUMMARY_TEXT; +import static com.android.notificationstudio.model.EditableItem.USES_CHRON; +import static com.android.notificationstudio.model.EditableItem.WHEN; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.BigPictureStyle; +import android.support.v4.app.NotificationCompat.BigTextStyle; +import android.support.v4.app.NotificationCompat.InboxStyle; + +import com.android.notificationstudio.model.EditableItemConstants; + +public class NotificationGenerator implements EditableItemConstants { + + public static Notification build(Context context) { + + PendingIntent noop = PendingIntent.getActivity(context, 0, new Intent(), 0); + + NotificationCompat.Builder builder = new NotificationCompat.Builder(context); + if (SMALL_ICON.hasValue()) + builder.setSmallIcon(SMALL_ICON.getValueInt()); + if (CONTENT_TITLE.hasValue()) + builder.setContentTitle(CONTENT_TITLE.getValueString()); + if (CONTENT_TEXT.hasValue()) + builder.setContentText(CONTENT_TEXT.getValueString()); + if (SUB_TEXT.hasValue()) + builder.setSubText(SUB_TEXT.getValueString()); + if (LARGE_ICON.hasValue()) + builder.setLargeIcon(LARGE_ICON.getValueBitmap()); + if (CONTENT_INFO.hasValue()) + builder.setContentInfo(CONTENT_INFO.getValueString()); + if (NUMBER.hasValue()) + builder.setNumber(NUMBER.getValueInt()); + if (WHEN.hasValue()) + builder.setWhen(WHEN.getValueLong()); + if (PROGRESS.hasValue() && PROGRESS.getValueBool()) + builder.setProgress(0, 0, true); + if (USES_CHRON.hasValue()) + builder.setUsesChronometer(USES_CHRON.getValueBool()); + if (ACTION1_ICON.hasValue()) + builder.addAction(ACTION1_ICON.getValueInt(), ACTION1_TEXT.getValueString(), noop); + if (ACTION2_ICON.hasValue()) + builder.addAction(ACTION2_ICON.getValueInt(), ACTION2_TEXT.getValueString(), noop); + if (ACTION3_ICON.hasValue()) + builder.addAction(ACTION3_ICON.getValueInt(), ACTION3_TEXT.getValueString(), noop); + + if (STYLE.hasValue()) + generateStyle(builder); + + // for older OSes + builder.setContentIntent(noop); + + return builder.build(); + } + + private static void generateStyle(NotificationCompat.Builder builder) { + Integer styleValue = STYLE.getValueInt(); + + if (STYLE_BIG_PICTURE.equals(styleValue)) { + BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle(); + if (PICTURE.hasValue()) + bigPicture.bigPicture(PICTURE.getValueBitmap()); + if (BIG_CONTENT_TITLE.hasValue()) + bigPicture.setBigContentTitle(BIG_CONTENT_TITLE.getValueString()); + if (SUMMARY_TEXT.hasValue()) + bigPicture.setSummaryText(SUMMARY_TEXT.getValueString()); + builder.setStyle(bigPicture); + } else if (STYLE_BIG_TEXT.equals(styleValue)) { + BigTextStyle bigText = new NotificationCompat.BigTextStyle(); + if (BIG_TEXT.hasValue()) + bigText.bigText(BIG_TEXT.getValueString()); + if (BIG_CONTENT_TITLE.hasValue()) + bigText.setBigContentTitle(BIG_CONTENT_TITLE.getValueString()); + if (SUMMARY_TEXT.hasValue()) + bigText.setSummaryText(SUMMARY_TEXT.getValueString()); + builder.setStyle(bigText); + } else if (STYLE_INBOX.equals(styleValue)) { + InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); + if (LINES.hasValue()) { + for (String line : LINES.getValueString().split("\\n")) { + inboxStyle.addLine(line); + } + } + if (BIG_CONTENT_TITLE.hasValue()) + inboxStyle.setBigContentTitle(BIG_CONTENT_TITLE.getValueString()); + if (SUMMARY_TEXT.hasValue()) + inboxStyle.setSummaryText(SUMMARY_TEXT.getValueString()); + builder.setStyle(inboxStyle); + } + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItem.java b/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItem.java new file mode 100644 index 000000000..54e03e019 --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItem.java @@ -0,0 +1,216 @@ +/* + * Copyright 2012 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.notificationstudio.model; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.android.notificationstudio.R; + +public enum EditableItem implements EditableItemConstants { + + PRESET(R.string.preset, TYPE_DROP_DOWN, CATEGORY_MAIN, + PRESET_BASIC, PRESET_EMAIL, PRESET_PHOTO, PRESET_CUSTOM), + SMALL_ICON(R.string.small_icon, TYPE_RESOURCE_ID, CATEGORY_MAIN, + SMALL_ICONS), + CONTENT_TITLE(R.string.content_title, TYPE_TEXT, CATEGORY_MAIN), + CONTENT_TEXT(R.string.content_text, TYPE_TEXT, CATEGORY_MAIN), + SUB_TEXT(R.string.sub_text, TYPE_TEXT, CATEGORY_MAIN), + LARGE_ICON(R.string.large_icon, TYPE_BITMAP, CATEGORY_MAIN), + CONTENT_INFO(R.string.content_info, TYPE_TEXT, CATEGORY_MAIN), + NUMBER(R.string.number, TYPE_INT, CATEGORY_MAIN), + WHEN(R.string.when, TYPE_DATETIME, CATEGORY_MAIN), + PROGRESS(R.string.progress, TYPE_BOOLEAN, CATEGORY_MAIN), + USES_CHRON(R.string.uses_chron, TYPE_BOOLEAN, CATEGORY_MAIN), + STYLE(R.string.style, TYPE_DROP_DOWN, CATEGORY_STYLE, + STYLE_NONE, STYLE_BIG_PICTURE, STYLE_BIG_TEXT, STYLE_INBOX), + PICTURE(R.string.picture, TYPE_BITMAP, CATEGORY_STYLE), + BIG_TEXT(R.string.big_text, TYPE_TEXT, CATEGORY_STYLE), + LINES(R.string.lines, TYPE_TEXT_LINES, CATEGORY_STYLE), + BIG_CONTENT_TITLE(R.string.big_content_title, TYPE_TEXT, CATEGORY_STYLE), + SUMMARY_TEXT(R.string.summary_text, TYPE_TEXT, CATEGORY_STYLE), + ACTION1_ICON(R.string.icon, TYPE_RESOURCE_ID, CATEGORY_ACTION1, + ACTION_ICONS), + ACTION1_TEXT(R.string.text, TYPE_TEXT, CATEGORY_ACTION1), + ACTION2_ICON(R.string.icon, TYPE_RESOURCE_ID, CATEGORY_ACTION2, + ACTION_ICONS), + ACTION2_TEXT(R.string.text, TYPE_TEXT, CATEGORY_ACTION2), + ACTION3_ICON(R.string.icon, TYPE_RESOURCE_ID, CATEGORY_ACTION3, + ACTION_ICONS), + ACTION3_TEXT(R.string.text, TYPE_TEXT, CATEGORY_ACTION3), + ; + + private final int mCaptionId; + private final int mType; + private final int mCategoryId; + + private Object[] mAvailableValues; + private Object mValue; + private boolean mVisible = true; + private Runnable mVisibilityListener; + + private EditableItem(int captionId, int type, int categoryId, Object... availableValues) { + mCaptionId = captionId; + mType = type; + mCategoryId = categoryId; + mAvailableValues = availableValues; + } + + // init + public static void initIfNecessary(Context context) { + if (PRESET.hasValue()) + return; + loadBitmaps(context, LARGE_ICON, LARGE_ICONS); + loadBitmaps(context, PICTURE, PICTURES); + PRESET.setValue(PRESET_BASIC); + } + + private static void loadBitmaps(Context context, EditableItem item, int[] bitmapResIds) { + Object[] largeIconBitmaps = new Object[bitmapResIds.length]; + Resources res = context.getResources(); + for (int i = 0; i < bitmapResIds.length; i++) + largeIconBitmaps[i] = BitmapFactory.decodeResource(res, bitmapResIds[i]); + item.setAvailableValues(largeIconBitmaps); + } + + // visibility + public boolean isVisible() { + return mVisible; + } + + public void setVisible(boolean visible) { + if (mVisible == visible) + return; + mVisible = visible; + if (mVisibilityListener != null) + mVisibilityListener.run(); + } + + public void setVisibilityListener(Runnable listener) { + mVisibilityListener = listener; + } + + // value + + public boolean hasValue() { + return mValue != null; + } + + public void setValue(Object value) { + if (mValue == value) + return; + mValue = value; + if (this == STYLE) + applyStyle(); + if (this == PRESET && !PRESET_CUSTOM.equals(value)) + applyPreset(); + } + + private void applyStyle() { + PICTURE.setVisible(STYLE_BIG_PICTURE.equals(mValue)); + BIG_TEXT.setVisible(STYLE_BIG_TEXT.equals(mValue)); + LINES.setVisible(STYLE_INBOX.equals(mValue)); + BIG_CONTENT_TITLE.setVisible(!STYLE_NONE.equals(mValue)); + SUMMARY_TEXT.setVisible(!STYLE_NONE.equals(mValue)); + } + + private void applyPreset() { + for (EditableItem item : values()) + if (item != PRESET) + item.setValue(null); + STYLE.setValue(STYLE_NONE); + if (PRESET_BASIC.equals(mValue)) { + SMALL_ICON.setValue(android.R.drawable.stat_notify_chat); + CONTENT_TITLE.setValue("Basic title"); + CONTENT_TEXT.setValue("Basic text"); + } else if (PRESET_EMAIL.equals(mValue)) { + SMALL_ICON.setValue(R.drawable.ic_notification_multiple_mail_holo_dark); + LARGE_ICON.setValue(LARGE_ICON.getAvailableValues()[3]); + CONTENT_TITLE.setValue("3 new messages"); + CONTENT_TEXT.setValue("Alice, Bob, Chuck"); + STYLE.setValue(STYLE_INBOX); + LINES.setValue("Alice: Re: Something\n" + + "Bob: Did you get the memo?\n" + + "Chuck: Limited time offer!"); + } else if (PRESET_PHOTO.equals(mValue)) { + SMALL_ICON.setValue(android.R.drawable.ic_menu_camera); + LARGE_ICON.setValue(LARGE_ICON.getAvailableValues()[2]); + CONTENT_TITLE.setValue("Sunset on the rocks"); + CONTENT_TEXT.setValue("800x534 | 405.1K"); + SUMMARY_TEXT.setValue(CONTENT_TEXT.getValueString()); + STYLE.setValue(STYLE_BIG_PICTURE); + PICTURE.setValue(PICTURE.getAvailableValues()[0]); + ACTION1_ICON.setValue(android.R.drawable.ic_menu_share); + ACTION1_TEXT.setValue("Share"); + } + } + + public Object getValue() { + return mValue; + } + + public String getValueString() { + return (String) mValue; + } + + public int getValueInt() { + return (Integer) mValue; + } + + public long getValueLong() { + return (Long) mValue; + } + + public boolean getValueBool() { + return (Boolean) mValue; + } + + public Bitmap getValueBitmap() { + return (Bitmap) mValue; + } + + // available values + + public Object[] getAvailableValues() { + return mAvailableValues; + } + + public Integer[] getAvailableValuesInteger() { + Integer[] integers = new Integer[mAvailableValues.length]; + System.arraycopy(mAvailableValues, 0, integers, 0, integers.length); + return integers; + } + + public <T> void setAvailableValues(T... values) { + mAvailableValues = values; + } + + public String getCaption(Context context) { + return context.getString(mCaptionId); + } + + public String getCategory(Context context) { + return context.getString(mCategoryId); + } + + public int getType() { + return mType; + } + +} diff --git a/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItemConstants.java b/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItemConstants.java new file mode 100644 index 000000000..d4defdf0c --- /dev/null +++ b/apps/NotificationStudio/src/com/android/notificationstudio/model/EditableItemConstants.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012 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.notificationstudio.model; + +import com.android.notificationstudio.R; + +public interface EditableItemConstants { + + public static final int TYPE_TEXT = 0; + public static final int TYPE_DROP_DOWN = 1; + public static final int TYPE_RESOURCE_ID = 2; + public static final int TYPE_BITMAP = 3; + public static final int TYPE_INT = 4; + public static final int TYPE_DATETIME = 5; + public static final int TYPE_BOOLEAN = 6; + public static final int TYPE_TEXT_LINES = 7; + + public static final int CATEGORY_MAIN = R.string.properties; + public static final int CATEGORY_STYLE = R.string.style; + public static final int CATEGORY_ACTION1 = R.string.action_1; + public static final int CATEGORY_ACTION2 = R.string.action_2; + public static final int CATEGORY_ACTION3 = R.string.action_3; + + public static final Integer PRESET_CUSTOM = R.string.preset_custom; + public static final Integer PRESET_BASIC = R.string.preset_basic; + public static final Integer PRESET_EMAIL = R.string.preset_email; + public static final Integer PRESET_PHOTO = R.string.preset_photo; + + public static final Integer STYLE_NONE = R.string.style_none; + public static final Integer STYLE_BIG_PICTURE = R.string.style_big_picture; + public static final Integer STYLE_BIG_TEXT = R.string.style_big_text; + public static final Integer STYLE_INBOX = R.string.style_inbox; + + public static final Object[] SMALL_ICONS = new Object[] { + android.R.drawable.stat_sys_warning, + android.R.drawable.stat_sys_download_done, + android.R.drawable.stat_notify_chat, + android.R.drawable.stat_notify_sync, + android.R.drawable.stat_notify_more, + android.R.drawable.stat_notify_sdcard, + android.R.drawable.stat_sys_data_bluetooth, + android.R.drawable.stat_notify_voicemail, + android.R.drawable.stat_sys_speakerphone, + android.R.drawable.ic_menu_camera, + android.R.drawable.ic_menu_share, + R.drawable.ic_notification_multiple_mail_holo_dark + }; + + public static final Object[] ACTION_ICONS = SMALL_ICONS; + + public static final int[] LARGE_ICONS = new int[]{ + R.drawable.romainguy_rockaway, + R.drawable.android_logo, + R.drawable.romain, + R.drawable.ic_notification_multiple_mail_holo_dark + }; + + public static final int[] PICTURES = LARGE_ICONS; + +} |