android/sdremote/res/drawable-hdpi/handle_default.9.png                      
|binary
 android/sdremote/res/drawable-hdpi/handle_light.9.png                        
|binary
 android/sdremote/res/drawable-ldpi/handle_default.9.png                      
|binary
 android/sdremote/res/drawable-ldpi/handle_light.9.png                        
|binary
 android/sdremote/res/drawable-mdpi/handle_default.9.png                      
|binary
 android/sdremote/res/drawable-mdpi/handle_light.9.png                        
|binary
 android/sdremote/res/drawable-xhdpi/handle_default.9.png                     
|binary
 android/sdremote/res/drawable-xhdpi/handle_light.9.png                       
|binary
 android/sdremote/res/drawable/handle.xml                                     | 
   9 
 android/sdremote/res/layout/fragment_presentation.xml                        | 
  63 -
 android/sdremote/res/values/attrs.xml                                        | 
  10 
 android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java | 
   5 
 android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java | 
 140 +++
 android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java    | 
   2 
 android/sdremote/src/org/libreoffice/impressremote/communication/Client.java | 
   1 
 android/sdremote/src/pl/polidea/coverflow/AbstractCoverFlowImageAdapter.java | 
 125 +++
 android/sdremote/src/pl/polidea/coverflow/CoverFlow.java                     | 
 388 ++++++++++
 android/sdremote/src/pl/polidea/coverflow/ReflectingImageAdapter.java        | 
 129 +++
 android/sdremote/src/pl/polidea/coverflow/ResourceImageAdapter.java          | 
  90 ++
 dev/null                                                                     
|binary
 20 files changed, 911 insertions(+), 51 deletions(-)

New commits:
commit 14eeca49cd3c34b0a9caa6fa3a2070346935c514
Author: Andrzej J.R. Hunt <[email protected]>
Date:   Tue Jul 24 11:46:48 2012 +0200

    Added cover flow.
    
    Change-Id: I7ffc47269a2e0b1fea4ec4dbcf6c03cdc37d4721

diff --git a/android/sdremote/res/layout/fragment_presentation.xml 
b/android/sdremote/res/layout/fragment_presentation.xml
index 3da7e09..fb50148 100644
--- a/android/sdremote/res/layout/fragment_presentation.xml
+++ b/android/sdremote/res/layout/fragment_presentation.xml
@@ -1,16 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
+    android:id="@+id/presentation_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:id="@+id/presentation_layout">
+    android:orientation="vertical" >
 
-    <ImageView
-        android:id="@+id/imageView1"
-        android:layout_width="wrap_content"
+    <pl.polidea.coverflow.CoverFlow
+        
xmlns:coverflow="http://schemas.android.com/apk/res/org.libreoffice.impressremote";
+        android:id="@+id/presentation_coverflow"
+        android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:contentDescription="TODO"
-        android:src="@drawable/testimage" />
+        android:layout_marginTop="5dip"
+        coverflow:imageHeight="150dip"
+        coverflow:imageReflectionRatio="0.2"
+        coverflow:imageWidth="100dip"
+        coverflow:reflectionGap="2dip"
+        coverflow:withReflection="true" />
 
     <ImageView
         android:id="@+id/presentation_handle"
@@ -25,12 +30,12 @@
         android:src="@drawable/handle" />
 
     <ScrollView
-        android:id="@+id/scrollView1"
+        android:id="@+id/presentation_scrollview"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" >
 
         <WebView
-            android:id="@+id/textView1"
+            android:id="@+id/presentation_notes"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
     </ScrollView>
diff --git a/android/sdremote/res/values/attrs.xml 
b/android/sdremote/res/values/attrs.xml
new file mode 100644
index 0000000..43de3bc
--- /dev/null
+++ b/android/sdremote/res/values/attrs.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+     <declare-styleable name="CoverFlow">
+        <attr name="imageWidth" format="dimension" />
+        <attr name="imageHeight" format="dimension" />
+        <attr name="withReflection" format="boolean" />
+        <attr name="reflectionGap" format="dimension" />
+        <attr name="imageReflectionRatio" format="float" />
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
index e06d2b5..8806610 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
@@ -69,8 +69,10 @@ public class PresentationActivity extends Activity {
                        mCommunicationService = ((CommunicationService.CBinder) 
aService)
                                        .getService();
                        mCommunicationService.setActivityMessenger(mMessenger);
+
+                       mPresentationFragment
+                                       
.setCommunicationService(mCommunicationService);
                        
mThumbnailFragment.setCommunicationService(mCommunicationService);
-                       // TODO: add mCommunicationSercie to all fragments.
 
                }
 
@@ -85,6 +87,7 @@ public class PresentationActivity extends Activity {
        protected class MessageHandler extends Handler {
                @Override
                public void handleMessage(Message aMessage) {
+                       mPresentationFragment.handleMessage(aMessage);
                        mThumbnailFragment.handleMessage(aMessage);
                        // Bundle aData = aMessage.getData();
                        // TODO: pass to fragments
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
index c031986..28ba8d0 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
@@ -1,8 +1,15 @@
 package org.libreoffice.impressremote;
 
+import org.libreoffice.impressremote.communication.CommunicationService;
+import org.libreoffice.impressremote.communication.SlideShow;
+
+import pl.polidea.coverflow.AbstractCoverFlowImageAdapter;
+import pl.polidea.coverflow.CoverFlow;
 import android.app.Fragment;
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.os.Message;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -10,16 +17,20 @@ import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.webkit.WebView;
+import android.widget.AdapterView;
 import android.widget.ImageView;
 
 public class PresentationFragment extends Fragment {
 
-       private View mTopView;
+       private CoverFlow mTopView;
        private ImageView mHandle;
        private View mLayout;
-
+       private WebView mNotes;
        private Context mContext;
 
+       private CommunicationService mCommunicationService;
+       private SlideShow mSlideShow;
+
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                mContext = container.getContext();
@@ -27,20 +38,25 @@ public class PresentationFragment extends Fragment {
                View v = inflater.inflate(R.layout.fragment_presentation, 
container,
                                false);
 
-               WebView mWebView = (WebView) v.findViewById(R.id.textView1);
+               mNotes = (WebView) v.findViewById(R.id.presentation_notes);
 
                String summary = "<html><body>This is just a 
test<br/><ul><li>And item</li><li>And again</li></ul>More 
text<br/>Blabla<br/>Blabla<br/>blabla<br/>Blabla</body></html>";
-               mWebView.loadData(summary, "text/html", null);
+               mNotes.loadData(summary, "text/html", null);
 
-               mTopView = v.findViewById(R.id.imageView1);
+               mTopView = (CoverFlow) 
v.findViewById(R.id.presentation_coverflow);
                mLayout = v.findViewById(R.id.presentation_layout);
 
                mHandle = (ImageView) v.findViewById(R.id.presentation_handle);
                mHandle.setOnTouchListener(new SizeListener());
 
+               if (mCommunicationService != null && mSlideShow != null) {
+                       mTopView.setAdapter(new ThumbnailAdapter(mContext, 
mSlideShow));
+               }
+
                return v;
        }
 
+       // -------------------------------------------------- RESIZING LISTENER 
----
        private class SizeListener implements OnTouchListener {
 
                @Override
@@ -75,4 +91,90 @@ public class PresentationFragment extends Fragment {
                        return true;
                }
        }
+
+       // ----------------------------------------------------- CLICK LISTENER 
----
+       protected class ClickListener implements 
AdapterView.OnItemClickListener {
+               public void onItemClick(AdapterView<?> parent, View v, int 
position,
+                               long id) {
+                       if (mCommunicationService != null)
+                               
mCommunicationService.getTransmitter().gotoSlide(position);
+               }
+       }
+
+       // ---------------------------------------------------- MESSAGE HANDLER 
----
+       public void setCommunicationService(
+                       CommunicationService aCommunicationService) {
+               mCommunicationService = aCommunicationService;
+               mSlideShow = mCommunicationService.getSlideShow();
+               if (mTopView != null) {
+                       mTopView.setAdapter(new ThumbnailAdapter(mContext, 
mSlideShow));
+               }
+       }
+
+       public void handleMessage(Message aMessage) {
+               Bundle aData = aMessage.getData();
+               switch (aMessage.what) {
+               case CommunicationService.MSG_SLIDE_CHANGED:
+                       int aSlide = aData.getInt("slide_number");
+                       mTopView.setSelection(aSlide, true);
+                       break;
+               case CommunicationService.MSG_SLIDE_PREVIEW:
+                       int aNSlide = aData.getInt("slide_number");
+                       if (mTopView.getSelectedItemPosition() == aNSlide) {
+                               // mTopView. // TODO: update the current item
+                       }
+                       break;
+
+               }
+       }
+
+       // ------------------------------------------------- THUMBNAIL ADAPTER 
----
+       protected class ThumbnailAdapter extends AbstractCoverFlowImageAdapter {
+
+               private Context mContext;
+
+               private SlideShow mSlideShow;
+
+               public ThumbnailAdapter(Context aContext, SlideShow aSlideShow) 
{
+                       mContext = aContext;
+                       mSlideShow = aSlideShow;
+               }
+
+               @Override
+               public int getCount() {
+                       return mSlideShow.getSize();
+               }
+
+               // @Override
+               // public View getView(int position, View convertView, 
ViewGroup parent)
+               // {
+               // LayoutInflater aInflater = (LayoutInflater) mContext
+               // .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+               // View v = aInflater.inflate(R.layout.slide_thumbnail, null);
+               //
+               // ImageView aImage = (ImageView) 
v.findViewById(R.id.sub_thumbnail);
+               // TextView aText = (TextView) v.findViewById(R.id.sub_number);
+               //
+               // // Do the image & number styling
+               // int aBorderWidth = getResources().getInteger(
+               // R.integer.thumbnail_border_width);
+               // aImage.setPadding(aBorderWidth, aBorderWidth, aBorderWidth,
+               // aBorderWidth);
+               //
+               // Bitmap aBitmap = mSlideShow.getImage(position);
+               // if (aBitmap != null) {
+               // aImage.setImageBitmap(aBitmap);
+               // }
+               //
+               // aText.setText(String.valueOf(position + 1));
+               //
+               // return v;
+               // }
+
+               @Override
+               protected Bitmap createBitmap(int position) {
+                       Bitmap aBitmap = mSlideShow.getImage(position);
+                       return aBitmap;
+               }
+       }
 }
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java 
b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
index b1ed882..de07603 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
@@ -101,8 +101,6 @@ public class ThumbnailFragment extends Fragment {
                }
        }
 
-       // ------------------------------------------------- SERVICE CONNECTION 
----
-
        // ----------------------------------------------------- CLICK LISTENER 
----
        protected class ClickListener implements 
AdapterView.OnItemClickListener {
                public void onItemClick(AdapterView<?> parent, View v, int 
position,
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
index b3209b8..bb76df9 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
@@ -60,7 +60,6 @@ public abstract class Client {
                                String aTemp;
                                // read until empty line
                                while ((aTemp = aReader.readLine()).length() != 
0) {
-                                       System.out.println("Read:" + aTemp);
                                        aList.add(aTemp);
                                }
                                mReceiver.parseCommand(aList);
diff --git 
a/android/sdremote/src/pl/polidea/coverflow/AbstractCoverFlowImageAdapter.java 
b/android/sdremote/src/pl/polidea/coverflow/AbstractCoverFlowImageAdapter.java
new file mode 100644
index 0000000..f60975f
--- /dev/null
+++ 
b/android/sdremote/src/pl/polidea/coverflow/AbstractCoverFlowImageAdapter.java
@@ -0,0 +1,125 @@
+package pl.polidea.coverflow;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+
+/**
+ * This class is an adapter that provides base, abstract class for images
+ * adapter.
+ *
+ */
+public abstract class AbstractCoverFlowImageAdapter extends BaseAdapter {
+
+       /** The Constant TAG. */
+       private static final String TAG = AbstractCoverFlowImageAdapter.class
+                       .getSimpleName();
+
+       /** The width. */
+       private float width = 0;
+
+       /** The height. */
+       private float height = 0;
+
+       /** The bitmap map. */
+       private final Map<Integer, WeakReference<Bitmap>> bitmapMap = new 
HashMap<Integer, WeakReference<Bitmap>>();
+
+       public AbstractCoverFlowImageAdapter() {
+               super();
+       }
+
+       /**
+        * Set width for all pictures.
+        *
+        * @param width
+        *            picture height
+        */
+       public synchronized void setWidth(final float width) {
+               this.width = width;
+       }
+
+       /**
+        * Set height for all pictures.
+        *
+        * @param height
+        *            picture height
+        */
+       public synchronized void setHeight(final float height) {
+               this.height = height;
+       }
+
+       @Override
+       public final Bitmap getItem(final int position) {
+               final WeakReference<Bitmap> weakBitmapReference = bitmapMap
+                               .get(position);
+               if (weakBitmapReference != null) {
+                       final Bitmap bitmap = weakBitmapReference.get();
+                       if (bitmap == null) {
+                               Log.v(TAG, "Empty bitmap reference at position: 
" + position
+                                               + ":" + this);
+                       } else {
+                               Log.v(TAG, "Reusing bitmap item at position: " 
+ position + ":"
+                                               + this);
+                               return bitmap;
+                       }
+               }
+               Log.v(TAG, "Creating item at position: " + position + ":" + 
this);
+               final Bitmap bitmap = createBitmap(position);
+               bitmapMap.put(position, new WeakReference<Bitmap>(bitmap));
+               Log.v(TAG, "Created item at position: " + position + ":" + 
this);
+               return bitmap;
+       }
+
+       /**
+        * Creates new bitmap for the position specified.
+        *
+        * @param position
+        *            position
+        * @return Bitmap created
+        */
+       protected abstract Bitmap createBitmap(int position);
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see android.widget.Adapter#getItemId(int)
+        */
+       @Override
+       public final synchronized long getItemId(final int position) {
+               return position;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see android.widget.Adapter#getView(int, android.view.View,
+        * android.view.ViewGroup)
+        */
+       @Override
+       public final synchronized ImageView getView(final int position,
+                       final View convertView, final ViewGroup parent) {
+               ImageView imageView;
+               if (convertView == null) {
+                       final Context context = parent.getContext();
+                       Log.v(TAG, "Creating Image view at position: " + 
position + ":"
+                                       + this);
+                       imageView = new ImageView(context);
+                       imageView.setLayoutParams(new 
CoverFlow.LayoutParams((int) width,
+                                       (int) height));
+               } else {
+                       Log.v(TAG, "Reusing view at position: " + position + 
":" + this);
+                       imageView = (ImageView) convertView;
+               }
+               imageView.setImageBitmap(getItem(position));
+               return imageView;
+       }
+
+}
diff --git a/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java 
b/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java
new file mode 100644
index 0000000..09da2a0
--- /dev/null
+++ b/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2010 Neil Davies
+ *
+ * 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.
+ *
+ * This code is base on the Android Gallery widget and was Created
+ * by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget
+ *
+ * @author Neil Davies
+ */
+package pl.polidea.coverflow;
+
+import org.libreoffice.impressremote.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Camera;
+import android.graphics.Matrix;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Transformation;
+import android.widget.Gallery;
+import android.widget.ImageView;
+import android.widget.SpinnerAdapter;
+
+/**
+ * Cover Flow implementation.
+ *
+ */
+public class CoverFlow extends Gallery {
+
+       /**
+        * Graphics Camera used for transforming the matrix of ImageViews.
+        */
+       private final Camera mCamera = new Camera();
+
+       /**
+        * The maximum angle the Child ImageView will be rotated by.
+        */
+       private int mMaxRotationAngle = 60;
+
+       /**
+        * The maximum zoom on the centre Child.
+        */
+       private int mMaxZoom = -120;
+
+       /**
+        * The Centre of the Coverflow.
+        */
+       private int mCoveflowCenter;
+
+       /** The image height. */
+       private float imageHeight;
+
+       /** The image width. */
+       private float imageWidth;
+
+       /** The reflection gap. */
+       private float reflectionGap;
+
+       /** The with reflection. */
+       private boolean withReflection;
+
+       /** The image reflection ratio. */
+       private float imageReflectionRatio;
+
+       /**
+        * Gets the image height.
+        *
+        * @return the image height
+        */
+       public float getImageHeight() {
+               return imageHeight;
+       }
+
+       /**
+        * Sets the image height.
+        *
+        * @param imageHeight
+        *            the new image height
+        */
+       public void setImageHeight(final float imageHeight) {
+               this.imageHeight = imageHeight;
+       }
+
+       /**
+        * Gets the image width.
+        *
+        * @return the image width
+        */
+       public float getImageWidth() {
+               return imageWidth;
+       }
+
+       /**
+        * Sets the image width.
+        *
+        * @param imageWidth
+        *            the new image width
+        */
+       public void setImageWidth(final float imageWidth) {
+               this.imageWidth = imageWidth;
+       }
+
+       /**
+        * Gets the reflection gap.
+        *
+        * @return the reflection gap
+        */
+       public float getReflectionGap() {
+               return reflectionGap;
+       }
+
+       /**
+        * Sets the reflection gap.
+        *
+        * @param reflectionGap
+        *            the new reflection gap
+        */
+       public void setReflectionGap(final float reflectionGap) {
+               this.reflectionGap = reflectionGap;
+       }
+
+       /**
+        * Checks if is with reflection.
+        *
+        * @return true, if is with reflection
+        */
+       public boolean isWithReflection() {
+               return withReflection;
+       }
+
+       /**
+        * Sets the with reflection.
+        *
+        * @param withReflection
+        *            the new with reflection
+        */
+       public void setWithReflection(final boolean withReflection) {
+               this.withReflection = withReflection;
+       }
+
+       /**
+        * Sets the image reflection ratio.
+        *
+        * @param imageReflectionRatio
+        *            the new image reflection ratio
+        */
+       public void setImageReflectionRatio(final float imageReflectionRatio) {
+               this.imageReflectionRatio = imageReflectionRatio;
+       }
+
+       /**
+        * Gets the image reflection ratio.
+        *
+        * @return the image reflection ratio
+        */
+       public float getImageReflectionRatio() {
+               return imageReflectionRatio;
+       }
+
+       public CoverFlow(final Context context) {
+               super(context);
+               this.setStaticTransformationsEnabled(true);
+       }
+
+       public CoverFlow(final Context context, final AttributeSet attrs) {
+               this(context, attrs, android.R.attr.galleryStyle);
+       }
+
+       public CoverFlow(final Context context, final AttributeSet attrs,
+                       final int defStyle) {
+               super(context, attrs, defStyle);
+               parseAttributes(context, attrs);
+               this.setStaticTransformationsEnabled(true);
+       }
+
+       /**
+        * Get the max rotational angle of the image.
+        *
+        * @return the mMaxRotationAngle
+        */
+       public int getMaxRotationAngle() {
+               return mMaxRotationAngle;
+       }
+
+       /**
+        * Sets the.
+        *
+        * @param adapter
+        *            the new adapter
+        */
+       @Override
+       public void setAdapter(final SpinnerAdapter adapter) {
+               if (!(adapter instanceof AbstractCoverFlowImageAdapter)) {
+                       throw new IllegalArgumentException(
+                                       "The adapter should derive from "
+                                                       + 
AbstractCoverFlowImageAdapter.class
+                                                                       
.getName());
+               }
+               final AbstractCoverFlowImageAdapter coverAdapter = 
(AbstractCoverFlowImageAdapter) adapter;
+               coverAdapter.setWidth(imageWidth);
+               coverAdapter.setHeight(imageHeight);
+               if (withReflection) {
+                       final ReflectingImageAdapter reflectAdapter = new 
ReflectingImageAdapter(
+                                       coverAdapter);
+                       reflectAdapter.setReflectionGap(reflectionGap);
+                       reflectAdapter.setWidthRatio(imageReflectionRatio);
+                       reflectAdapter.setWidth(imageWidth);
+                       reflectAdapter.setHeight(imageHeight * (1 + 
imageReflectionRatio));
+                       super.setAdapter(reflectAdapter);
+               } else {
+                       super.setAdapter(adapter);
+               }
+       }
+
+       /**
+        * Set the max rotational angle of each image.
+        *
+        * @param maxRotationAngle
+        *            the mMaxRotationAngle to set
+        */
+       public void setMaxRotationAngle(final int maxRotationAngle) {
+               mMaxRotationAngle = maxRotationAngle;
+       }
+
+       /**
+        * Get the Max zoom of the centre image.
+        *
+        * @return the mMaxZoom
+        */
+       public int getMaxZoom() {
+               return mMaxZoom;
+       }
+
+       /**
+        * Set the max zoom of the centre image.
+        *
+        * @param maxZoom
+        *            the mMaxZoom to set
+        */
+       public void setMaxZoom(final int maxZoom) {
+               mMaxZoom = maxZoom;
+       }
+
+       /**
+        * Get the Centre of the Coverflow.
+        *
+        * @return The centre of this Coverflow.
+        */
+       private int getCenterOfCoverflow() {
+               return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
+                               + getPaddingLeft();
+       }
+
+       /**
+        * Get the Centre of the View.
+        *
+        * @return The centre of the given view.
+        */
+       private static int getCenterOfView(final View view) {
+               return view.getLeft() + view.getWidth() / 2;
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * @see #setStaticTransformationsEnabled(boolean)
+        */
+       @Override
+       protected boolean getChildStaticTransformation(final View child,
+                       final Transformation t) {
+
+               final int childCenter = getCenterOfView(child);
+               final int childWidth = child.getWidth();
+               int rotationAngle = 0;
+
+               t.clear();
+               t.setTransformationType(Transformation.TYPE_MATRIX);
+
+               if (childCenter == mCoveflowCenter) {
+                       transformImageBitmap((ImageView) child, t, 0);
+               } else {
+                       rotationAngle = (int) ((float) (mCoveflowCenter - 
childCenter)
+                                       / childWidth * mMaxRotationAngle);
+                       if (Math.abs(rotationAngle) > mMaxRotationAngle) {
+                               rotationAngle = rotationAngle < 0 ? 
-mMaxRotationAngle
+                                               : mMaxRotationAngle;
+                       }
+                       transformImageBitmap((ImageView) child, t, 
rotationAngle);
+               }
+
+               return true;
+       }
+
+       /**
+        * This is called during layout when the size of this view has changed. 
If
+        * you were just added to the view hierarchy, you're called with the old
+        * values of 0.
+        *
+        * @param w
+        *            Current width of this view.
+        * @param h
+        *            Current height of this view.
+        * @param oldw
+        *            Old width of this view.
+        * @param oldh
+        *            Old height of this view.
+        */
+       @Override
+       protected void onSizeChanged(final int w, final int h, final int oldw,
+                       final int oldh) {
+               mCoveflowCenter = getCenterOfCoverflow();
+               super.onSizeChanged(w, h, oldw, oldh);
+       }
+
+       /**
+        * Transform the Image Bitmap by the Angle passed.
+        *
+        * @param imageView
+        *            ImageView the ImageView whose bitmap we want to rotate
+        * @param t
+        *            transformation
+        * @param rotationAngle
+        *            the Angle by which to rotate the Bitmap
+        */
+       private void transformImageBitmap(final ImageView child,
+                       final Transformation t, final int rotationAngle) {
+               mCamera.save();
+               final Matrix imageMatrix = t.getMatrix();
+
+               final int height = child.getLayoutParams().height;
+
+               final int width = child.getLayoutParams().width;
+               final int rotation = Math.abs(rotationAngle);
+
+               mCamera.translate(0.0f, 0.0f, 100.0f);
+
+               // As the angle of the view gets less, zoom in
+               if (rotation < mMaxRotationAngle) {
+                       final float zoomAmount = (float) (mMaxZoom + rotation * 
1.5);
+                       mCamera.translate(0.0f, 0.0f, zoomAmount);
+               }
+
+               mCamera.rotateY(rotationAngle);
+               mCamera.getMatrix(imageMatrix);
+               imageMatrix.preTranslate(-(width / 2.0f), -(height / 2.0f));
+               imageMatrix.postTranslate((width / 2.0f), (height / 2.0f));
+               mCamera.restore();
+       }
+
+       /**
+        * Parses the attributes.
+        *
+        * @param context
+        *            the context
+        * @param attrs
+        *            the attrs
+        */
+       private void parseAttributes(final Context context, final AttributeSet 
attrs) {
+               final TypedArray a = context.obtainStyledAttributes(attrs,
+                               R.styleable.CoverFlow);
+               try {
+                       imageWidth = 
a.getDimension(R.styleable.CoverFlow_imageWidth, 480);
+                       imageHeight = 
a.getDimension(R.styleable.CoverFlow_imageHeight, 320);
+                       withReflection = 
a.getBoolean(R.styleable.CoverFlow_withReflection,
+                                       false);
+                       imageReflectionRatio = a.getFloat(
+                                       
R.styleable.CoverFlow_imageReflectionRatio, 0.2f);
+                       reflectionGap = 
a.getDimension(R.styleable.CoverFlow_reflectionGap,
+                                       4);
+                       setSpacing(-15);
+               } finally {
+                       a.recycle();
+               }
+       }
+
+}
\ No newline at end of file
diff --git 
a/android/sdremote/src/pl/polidea/coverflow/ReflectingImageAdapter.java 
b/android/sdremote/src/pl/polidea/coverflow/ReflectingImageAdapter.java
new file mode 100644
index 0000000..ff04475
--- /dev/null
+++ b/android/sdremote/src/pl/polidea/coverflow/ReflectingImageAdapter.java
@@ -0,0 +1,129 @@
+package pl.polidea.coverflow;
+
+import android.R.color;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Shader.TileMode;
+
+/**
+ * This adapter provides reflected images from linked adapter.
+ *
+ * @author potiuk
+ *
+ */
+public class ReflectingImageAdapter extends AbstractCoverFlowImageAdapter {
+
+       /** The linked adapter. */
+       private final AbstractCoverFlowImageAdapter linkedAdapter;
+       /**
+        * Gap between the image and its reflection.
+        */
+       private float reflectionGap;
+
+       /** The image reflection ratio. */
+       private float imageReflectionRatio;
+
+       /**
+        * Sets the width ratio.
+        *
+        * @param imageReflectionRatio
+        *            the new width ratio
+        */
+       public void setWidthRatio(final float imageReflectionRatio) {
+               this.imageReflectionRatio = imageReflectionRatio;
+       }
+
+       /**
+        * Creates reflecting adapter.
+        *
+        * @param linkedAdapter
+        *            adapter that provides images to get reflections
+        */
+       public ReflectingImageAdapter(
+                       final AbstractCoverFlowImageAdapter linkedAdapter) {
+               super();
+               this.linkedAdapter = linkedAdapter;
+       }
+
+       /**
+        * Sets the reflection gap.
+        *
+        * @param reflectionGap
+        *            the new reflection gap
+        */
+       public void setReflectionGap(final float reflectionGap) {
+               this.reflectionGap = reflectionGap;
+       }
+
+       /**
+        * Gets the reflection gap.
+        *
+        * @return the reflection gap
+        */
+       public float getReflectionGap() {
+               return reflectionGap;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
pl.polidea.coverflow.AbstractCoverFlowImageAdapter#createBitmap(int)
+        */
+       @Override
+       protected Bitmap createBitmap(final int position) {
+               return createReflectedImages(linkedAdapter.getItem(position));
+       }
+
+       /**
+        * Creates the reflected images.
+        *
+        * @param originalImage
+        *            the original image
+        * @return true, if successful
+        */
+       public Bitmap createReflectedImages(final Bitmap originalImage) {
+               final int width = originalImage.getWidth();
+               final int height = originalImage.getHeight();
+               final Matrix matrix = new Matrix();
+               matrix.preScale(1, -1);
+               final Bitmap reflectionImage = 
Bitmap.createBitmap(originalImage, 0,
+                               (int) (height * imageReflectionRatio), width,
+                               (int) (height - height * imageReflectionRatio), 
matrix,
+                               false);
+               final Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
+                               (int) (height + height * imageReflectionRatio),
+                               Config.ARGB_8888);
+               final Canvas canvas = new Canvas(bitmapWithReflection);
+               canvas.drawBitmap(originalImage, 0, 0, null);
+               final Paint deafaultPaint = new Paint();
+               deafaultPaint.setColor(color.transparent);
+               canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, 
null);
+               final Paint paint = new Paint();
+               final LinearGradient shader = new LinearGradient(0,
+                               originalImage.getHeight(), 0,
+                               bitmapWithReflection.getHeight() + 
reflectionGap,
+                               0x70ffffff, 0x00ffffff, TileMode.CLAMP);
+               paint.setShader(shader);
+               paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+               canvas.drawRect(0, height, width, 
bitmapWithReflection.getHeight()
+                               + reflectionGap, paint);
+               return bitmapWithReflection;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see android.widget.Adapter#getCount()
+        */
+       @Override
+       public int getCount() {
+               return linkedAdapter.getCount();
+       }
+
+}
diff --git 
a/android/sdremote/src/pl/polidea/coverflow/ResourceImageAdapter.java 
b/android/sdremote/src/pl/polidea/coverflow/ResourceImageAdapter.java
new file mode 100644
index 0000000..469d0d1
--- /dev/null
+++ b/android/sdremote/src/pl/polidea/coverflow/ResourceImageAdapter.java
@@ -0,0 +1,90 @@
+package pl.polidea.coverflow;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.Log;
+
+/**
+ * This class is an adapter that provides images from a fixed set of resource
+ * ids. Bitmaps and ImageViews are kept as weak references so that they can be
+ * cleared by garbage collection when not needed.
+ *
+ */
+public class ResourceImageAdapter extends AbstractCoverFlowImageAdapter {
+
+       /** The Constant TAG. */
+       private static final String TAG = ResourceImageAdapter.class
+                       .getSimpleName();
+
+       /** The Constant DEFAULT_LIST_SIZE. */
+       private static final int DEFAULT_LIST_SIZE = 20;
+
+       /** The Constant IMAGE_RESOURCE_IDS. */
+       private static final List<Integer> IMAGE_RESOURCE_IDS = new 
ArrayList<Integer>(
+                       DEFAULT_LIST_SIZE);
+
+       /** The Constant DEFAULT_RESOURCE_LIST. */
+       private static final int[] DEFAULT_RESOURCE_LIST = {};
+       /** The bitmap map. */
+       private final Map<Integer, WeakReference<Bitmap>> bitmapMap = new 
HashMap<Integer, WeakReference<Bitmap>>();
+
+       private final Context context;
+
+       /**
+        * Creates the adapter with default set of resource images.
+        *
+        * @param context
+        *            context
+        */
+       public ResourceImageAdapter(final Context context) {
+               super();
+               this.context = context;
+               setResources(DEFAULT_RESOURCE_LIST);
+       }
+
+       /**
+        * Replaces resources with those specified.
+        *
+        * @param resourceIds
+        *            array of ids of resources.
+        */
+       public final synchronized void setResources(final int[] resourceIds) {
+               IMAGE_RESOURCE_IDS.clear();
+               for (final int resourceId : resourceIds) {
+                       IMAGE_RESOURCE_IDS.add(resourceId);
+               }
+               notifyDataSetChanged();
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see android.widget.Adapter#getCount()
+        */
+       @Override
+       public synchronized int getCount() {
+               return IMAGE_RESOURCE_IDS.size();
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
pl.polidea.coverflow.AbstractCoverFlowImageAdapter#createBitmap(int)
+        */
+       @Override
+       protected Bitmap createBitmap(final int position) {
+               Log.v(TAG, "creating item " + position);
+               final Bitmap bitmap = ((BitmapDrawable) context.getResources()
+                               .getDrawable(IMAGE_RESOURCE_IDS.get(position)))
+                               .getBitmap();
+               bitmapMap.put(position, new WeakReference<Bitmap>(bitmap));
+               return bitmap;
+       }
+}
\ No newline at end of file
commit 037fdae69e0be56b4470e7a21df4a3b9d36af01f
Author: Andrzej J.R. Hunt <[email protected]>
Date:   Tue Jul 24 11:05:12 2012 +0200

    Improved resizing handle, added visual feedback, limits.
    
    Change-Id: I6f1f9168dd53f660b676bf5050848ce509e11ae1

diff --git a/android/sdremote/res/drawable-hdpi/handle_default.9.png 
b/android/sdremote/res/drawable-hdpi/handle_default.9.png
new file mode 100644
index 0000000..d978f95
Binary files /dev/null and 
b/android/sdremote/res/drawable-hdpi/handle_default.9.png differ
diff --git a/android/sdremote/res/drawable-hdpi/handle_light.9.png 
b/android/sdremote/res/drawable-hdpi/handle_light.9.png
new file mode 100644
index 0000000..b0d7bef
Binary files /dev/null and 
b/android/sdremote/res/drawable-hdpi/handle_light.9.png differ
diff --git a/android/sdremote/res/drawable-ldpi/handle_default.9.png 
b/android/sdremote/res/drawable-ldpi/handle_default.9.png
new file mode 100644
index 0000000..d978f95
Binary files /dev/null and 
b/android/sdremote/res/drawable-ldpi/handle_default.9.png differ
diff --git a/android/sdremote/res/drawable-ldpi/handle_light.9.png 
b/android/sdremote/res/drawable-ldpi/handle_light.9.png
new file mode 100644
index 0000000..b0d7bef
Binary files /dev/null and 
b/android/sdremote/res/drawable-ldpi/handle_light.9.png differ
diff --git a/android/sdremote/res/drawable-mdpi/handle_default.9.png 
b/android/sdremote/res/drawable-mdpi/handle_default.9.png
new file mode 100644
index 0000000..d978f95
Binary files /dev/null and 
b/android/sdremote/res/drawable-mdpi/handle_default.9.png differ
diff --git a/android/sdremote/res/drawable-mdpi/handle_light.9.png 
b/android/sdremote/res/drawable-mdpi/handle_light.9.png
new file mode 100644
index 0000000..b0d7bef
Binary files /dev/null and 
b/android/sdremote/res/drawable-mdpi/handle_light.9.png differ
diff --git a/android/sdremote/res/drawable-xhdpi/handle_default.9.png 
b/android/sdremote/res/drawable-xhdpi/handle_default.9.png
new file mode 100644
index 0000000..d978f95
Binary files /dev/null and 
b/android/sdremote/res/drawable-xhdpi/handle_default.9.png differ
diff --git a/android/sdremote/res/drawable-xhdpi/handle_light.9.png 
b/android/sdremote/res/drawable-xhdpi/handle_light.9.png
new file mode 100644
index 0000000..b0d7bef
Binary files /dev/null and 
b/android/sdremote/res/drawable-xhdpi/handle_light.9.png differ
diff --git a/android/sdremote/res/drawable/handle.xml 
b/android/sdremote/res/drawable/handle.xml
new file mode 100644
index 0000000..9fda3d8
--- /dev/null
+++ b/android/sdremote/res/drawable/handle.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android";>
+
+    <item android:drawable="@drawable/handle_light" 
android:state_activated="true"/>
+    <item android:drawable="@drawable/handle_light" 
android:state_pressed="true"/>
+    <item android:drawable="@drawable/handle_light" 
android:state_focused="true"/>
+    <item android:drawable="@drawable/handle_default"/>
+
+</selector>
\ No newline at end of file
diff --git a/android/sdremote/res/drawable/handle_center.png 
b/android/sdremote/res/drawable/handle_center.png
deleted file mode 100644
index b591d35..0000000
Binary files a/android/sdremote/res/drawable/handle_center.png and /dev/null 
differ
diff --git a/android/sdremote/res/drawable/handle_line.png 
b/android/sdremote/res/drawable/handle_line.png
deleted file mode 100644
index ede5d81..0000000
Binary files a/android/sdremote/res/drawable/handle_line.png and /dev/null 
differ
diff --git a/android/sdremote/res/layout/fragment_presentation.xml 
b/android/sdremote/res/layout/fragment_presentation.xml
index 9331dc5..3da7e09 100644
--- a/android/sdremote/res/layout/fragment_presentation.xml
+++ b/android/sdremote/res/layout/fragment_presentation.xml
@@ -2,7 +2,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    android:id="@+id/presentation_layout">
 
     <ImageView
         android:id="@+id/imageView1"
@@ -11,40 +12,17 @@
         android:contentDescription="TODO"
         android:src="@drawable/testimage" />
 
-    <LinearLayout
-        android:layout_width="match_parent"
+    <ImageView
+        android:id="@+id/presentation_handle"
+        android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:id="@+id/presentation_handle" >
-
-        <ImageView
-            android:id="@+id/imageView4"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="0.5"
-            android:contentDescription="TODO"
-            android:paddingLeft="6dp"
-            android:scaleType="fitXY"
-            android:src="@drawable/handle_line" />
-
-        <ImageView
-            android:id="@+id/imageView3"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:contentDescription="TODO"
-            android:src="@drawable/handle_center" />
-
-        <ImageView
-            android:id="@+id/imageView2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="0.5"
-            android:maxWidth="500dp"
-            android:paddingRight="6dp"
-            android:scaleType="fitXY"
-            android:src="@drawable/handle_line"
-            android:contentDescription="TODO"/>
-    </LinearLayout>
+        android:layout_marginLeft="6dp"
+        android:layout_marginRight="6dp"
+        android:contentDescription="TODO"
+        android:paddingBottom="5dp"
+        android:paddingTop="5dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/handle" />
 
     <ScrollView
         android:id="@+id/scrollView1"
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
index 5ae47b3..c031986 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
@@ -1,6 +1,7 @@
 package org.libreoffice.impressremote;
 
 import android.app.Fragment;
+import android.content.Context;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -9,14 +10,20 @@ import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.webkit.WebView;
+import android.widget.ImageView;
 
 public class PresentationFragment extends Fragment {
 
        private View mTopView;
+       private ImageView mHandle;
+       private View mLayout;
+
+       private Context mContext;
 
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
-               // Inflate the layout for this fragment
+               mContext = container.getContext();
+
                View v = inflater.inflate(R.layout.fragment_presentation, 
container,
                                false);
 
@@ -26,9 +33,10 @@ public class PresentationFragment extends Fragment {
                mWebView.loadData(summary, "text/html", null);
 
                mTopView = v.findViewById(R.id.imageView1);
+               mLayout = v.findViewById(R.id.presentation_layout);
 
-               v.findViewById(R.id.presentation_handle).setOnTouchListener(
-                               new SizeListener());
+               mHandle = (ImageView) v.findViewById(R.id.presentation_handle);
+               mHandle.setOnTouchListener(new SizeListener());
 
                return v;
        }
@@ -41,9 +49,25 @@ public class PresentationFragment extends Fragment {
                        LayoutParams aParams = mTopView.getLayoutParams();
 
                        switch (aEvent.getAction()) {
+                       case MotionEvent.ACTION_DOWN:
+                               
mHandle.setImageResource(R.drawable.handle_light);
+                               break;
+                       case MotionEvent.ACTION_UP:
+                               
mHandle.setImageResource(R.drawable.handle_default);
+                               break;
                        case MotionEvent.ACTION_MOVE:
                                int aHeight = mTopView.getHeight();
                                aParams.height = aHeight + (int) 
(aEvent.getY());
+
+                               final int DRAG_MARGIN = 120;
+
+                               int aSize = mLayout.getHeight();
+                               if (aParams.height < DRAG_MARGIN) {
+                                       aParams.height = DRAG_MARGIN;
+                               } else if (aParams.height > aSize - 
DRAG_MARGIN) {
+                                       aParams.height = aSize - DRAG_MARGIN;
+                               }
+
                                mTopView.setLayoutParams(aParams);
                                break;
                        }
_______________________________________________
Libreoffice-commits mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to