[Libreoffice-commits] .: android/sdremote

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Aug 21 05:36:46 PDT 2012


 android/sdremote/res/layout-land/fragment_presentation.xml                       |   10 
 android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java     |    2 
 android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java     |   62 
 android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java |  197 --
 android/sdremote/src/pl/polidea/coverflow/CoverFlow.java                         |  690 +++++-----
 5 files changed, 391 insertions(+), 570 deletions(-)

New commits:
commit fa3a32a8dad94378c46e98bc46ae5216959f7bdd
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date:   Tue Aug 21 14:35:39 2012 +0200

    Fix losing communication service on screen rotation.
    
    Change-Id: I8ae72857ce65783fe79cd3b911b83b4c70deece6

diff --git a/android/sdremote/res/layout-land/fragment_presentation.xml b/android/sdremote/res/layout-land/fragment_presentation.xml
index 66de905..2f04f0e 100644
--- a/android/sdremote/res/layout-land/fragment_presentation.xml
+++ b/android/sdremote/res/layout-land/fragment_presentation.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res/org.libreoffice.impressremote"
     android:id="@+id/presentation_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -15,9 +16,10 @@
             android:id="@+id/presentation_coverflow"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginTop="5dip"
-            coverflow:imageHeight="150dip"
-            coverflow:imageWidth="180dip"
+            android:layout_margin="5dp"
+            android:layout_marginLeft="10dp"
+            coverflow:imageHeight="200dip"
+            coverflow:imageWidth="240dip"
             coverflow:withReflection="false" />
 
         <TextView
@@ -36,6 +38,8 @@
         android:layout_marginRight="6dp"
         android:contentDescription="@string/presentation_ui_resizehandle"
         android:paddingBottom="5dp"
+        android:paddingLeft="5dp"
+        android:paddingRight="10dp"
         android:paddingTop="5dp"
         android:scaleType="fitXY"
         android:src="@drawable/handle" />
diff --git a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
index 73325bc..4d21d40 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
@@ -112,8 +112,6 @@ public class PresentationActivity extends SherlockFragmentActivity {
             mCommunicationService = ((CommunicationService.CBinder) aService)
                             .getService();
 
-            mPresentationFragment
-                            .setCommunicationService(mCommunicationService);
             mThumbnailFragment.setCommunicationService(mCommunicationService);
 
         }
diff --git a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
index 3b7bdca..4e90ee0 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
@@ -6,9 +6,11 @@ import org.libreoffice.impressremote.communication.SlideShow;
 import pl.polidea.coverflow.AbstractCoverFlowImageAdapter;
 import pl.polidea.coverflow.CoverFlow;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -16,6 +18,7 @@ import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.RectF;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.support.v4.content.LocalBroadcastManager;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -39,7 +42,6 @@ public class PresentationFragment extends SherlockFragment {
     private TextView mNumberText;
 
     private CommunicationService mCommunicationService;
-    private SlideShow mSlideShow;
 
     private float mOriginalCoverflowWidth;
     private float mOriginalCoverflowHeight;
@@ -47,8 +49,37 @@ public class PresentationFragment extends SherlockFragment {
     private float mNewCoverflowWidth = 0;
     private float mNewCoverflowHeight = 0;
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName aClassName,
+                        IBinder aService) {
+            mCommunicationService = ((CommunicationService.CBinder) aService)
+                            .getService();
+
+            if (mTopView != null) {
+                mTopView.setAdapter(new ThumbnailAdapter(mContext,
+                                mCommunicationService.getSlideShow()));
+                mTopView.setSelection(mCommunicationService.getSlideShow()
+                                .getCurrentSlide(), true);
+                mTopView.setOnItemSelectedListener(new ClickListener());
+            }
+
+            updateSlideNumberDisplay();
+
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName aClassName) {
+            mCommunicationService = null;
+        }
+    };
+
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
+        getActivity().bindService(
+                        new Intent(getActivity().getApplicationContext(),
+                                        CommunicationService.class),
+                        mConnection, Context.BIND_IMPORTANT);
         mContext = getActivity().getApplicationContext();
         container.removeAllViews();
         View v = inflater.inflate(R.layout.fragment_presentation, container,
@@ -69,9 +100,6 @@ public class PresentationFragment extends SherlockFragment {
         mHandle = (ImageView) v.findViewById(R.id.presentation_handle);
         mHandle.setOnTouchListener(new SizeListener());
 
-        // Call again to set things up if necessary.
-        setCommunicationService(mCommunicationService);
-
         // Save the height/width for future reference
         mOriginalCoverflowHeight = mTopView.getImageHeight();
         mOriginalCoverflowWidth = mTopView.getImageWidth();
@@ -95,11 +123,13 @@ public class PresentationFragment extends SherlockFragment {
         LocalBroadcastManager
                         .getInstance(getActivity().getApplicationContext())
                         .registerReceiver(mListener, aFilter);
+
         return v;
     }
 
     @Override
     public void onDestroyView() {
+        getActivity().unbindService(mConnection);
         super.onDestroyView();
         LocalBroadcastManager
                         .getInstance(getActivity().getApplicationContext())
@@ -108,9 +138,11 @@ public class PresentationFragment extends SherlockFragment {
     }
 
     private void updateSlideNumberDisplay() {
-        int aSlide = mSlideShow.getCurrentSlide();
-        mNumberText.setText((aSlide + 1) + "/" + mSlideShow.getSize());
-        mNotes.loadData(mSlideShow.getNotes(aSlide), "text/html", null);
+        int aSlide = mCommunicationService.getSlideShow().getCurrentSlide();
+        mNumberText.setText((aSlide + 1) + "/"
+                        + mCommunicationService.getSlideShow().getSize());
+        mNotes.loadData(mCommunicationService.getSlideShow().getNotes(aSlide),
+                        "text/html", null);
     }
 
     // -------------------------------------------------- RESIZING LISTENER ----
@@ -207,22 +239,6 @@ public class PresentationFragment extends SherlockFragment {
     }
 
     // ---------------------------------------------------- MESSAGE HANDLER ----
-    public void setCommunicationService(
-                    CommunicationService aCommunicationService) {
-        mCommunicationService = aCommunicationService;
-        if (mCommunicationService == null)
-            return;
-
-        mSlideShow = mCommunicationService.getSlideShow();
-        if (mTopView != null && mSlideShow != null) {
-            mTopView.setAdapter(new ThumbnailAdapter(mContext, mSlideShow));
-            mTopView.setSelection(mSlideShow.getCurrentSlide(), true);
-            mTopView.setOnItemSelectedListener(new ClickListener());
-        }
-
-        updateSlideNumberDisplay();
-    }
-
     private BroadcastReceiver mListener = new BroadcastReceiver() {
 
         @Override
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java b/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java
deleted file mode 100644
index a63472f..0000000
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java
+++ /dev/null
@@ -1,197 +0,0 @@
-///* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-///*
-// * This file is part of the LibreOffice project.
-// *
-// * This Source Code Form is subject to the terms of the Mozilla Public
-// * License, v. 2.0. If a copy of the MPL was not distributed with this
-// * file, You can obtain one at http://mozilla.org/MPL/2.0/.
-// */
-//package org.libreoffice.impressremote.communication;
-//
-//import org.libreoffice.impressremote.PresentationActivity;
-//import org.libreoffice.impressremote.R;
-//import org.libreoffice.impressremote.communication.Server.Protocol;
-//
-//import android.app.Activity;
-//import android.content.ComponentName;
-//import android.content.Context;
-//import android.content.Intent;
-//import android.content.ServiceConnection;
-//import android.graphics.Bitmap;
-//import android.os.Bundle;
-//import android.os.Handler;
-//import android.os.IBinder;
-//import android.os.Message;
-//import android.os.Messenger;
-//import android.view.View;
-//import android.view.View.OnClickListener;
-//import android.widget.Button;
-//import android.widget.ImageView;
-//import android.widget.TextView;
-//
-//public class TestClient extends Activity {
-//
-//    private boolean mCurrentPreviewImageMissing = false;
-//
-//    private boolean mIsBound = false;
-//
-//    private CommunicationService mCommunicationService;
-//
-//    final Messenger mMessenger = new Messenger(new MessageHandler());
-//
-//    /** Called when the activity is first created. */
-//    @Override
-//    public void onCreate(Bundle savedInstanceState) {
-//        super.onCreate(savedInstanceState);
-//        setContentView(R.layout.testlayout);
-//        setupUI();
-//
-//    }
-//
-//    @Override
-//    protected void onResume() {
-//        super.onResume();
-//        doBindService();
-//
-//    }
-//
-//    // FIXME: move all necessary code to CommunicationService.onUnbind
-//
-//    @Override
-//    protected void onPause() {
-//        super.onPause();
-//    }
-//
-//    @Override
-//    public void onBackPressed() {
-//        // TODO Auto-generated method stub
-//        mCommunicationService.disconnect();
-//        stopService(new Intent(this, CommunicationService.class));
-//        doUnbindService();
-//        finish();
-//        super.onBackPressed();
-//    }
-//
-//    @Override
-//    protected void onStop() {
-//        // TODO Auto-generated method stub
-//        super.onStop();
-//        // mCommunicationService.disconnect();
-//        // stopService(new Intent(this, CommunicationService.class));
-//    }
-//
-//    private ServiceConnection mConnection = new ServiceConnection() {
-//        @Override
-//        public void onServiceConnected(ComponentName aClassName,
-//                        IBinder aService) {
-//            mCommunicationService = ((CommunicationService.CBinder) aService)
-//                            .getService();
-//            mCommunicationService.connectTo(new Server(Protocol.NETWORK,
-//                            "10.0.2.2", "TestServer", 0l));
-//            mCommunicationService.setActivityMessenger(mMessenger);
-//            enableButtons(true);
-//        }
-//
-//        @Override
-//        public void onServiceDisconnected(ComponentName aClassName) {
-//            mCommunicationService = null;
-//            enableButtons(false);
-//        }
-//    };
-//
-//    void doBindService() {
-//        Intent aIntent = new Intent(this, CommunicationService.class);
-//        startService(aIntent);
-//        bindService(aIntent, mConnection, Context.BIND_IMPORTANT);
-//        mIsBound = true;
-//    }
-//
-//    void doUnbindService() {
-//        mCommunicationService.setActivityMessenger(null);
-//        if (mIsBound) {
-//            unbindService(mConnection);
-//            mIsBound = false;
-//        }
-//    }
-//
-//    private Button mButtonNext;
-//
-//    private Button mButtonPrevious;
-//
-//    private ImageView mImageView;
-//
-//    private TextView mSlideLabel;
-//
-//    private void setupUI() {
-//        mButtonNext = (Button) findViewById(R.id.button_next);
-//        mButtonPrevious = (Button) findViewById(R.id.button_previous);
-//        mImageView = (ImageView) findViewById(R.id.image_preview);
-//        mSlideLabel = (TextView) findViewById(R.id.label_curSlide);
-//
-//        enableButtons(false);
-//
-//        mButtonNext.setOnClickListener(new OnClickListener() {
-//
-//            @Override
-//            public void onClick(View v) {
-//                mCommunicationService.getTransmitter().nextTransition();
-//
-//            }
-//
-//        });
-//
-//        mButtonPrevious.setOnClickListener(new OnClickListener() {
-//
-//            @Override
-//            public void onClick(View v) {
-//                mCommunicationService.getTransmitter().previousTransition();
-//
-//            }
-//
-//        });
-//
-//        Button mThumbnailButton = (Button) findViewById(R.id.button_thumbnail);
-//
-//        mThumbnailButton.setOnClickListener(new OnClickListener() {
-//            @Override
-//            public void onClick(View v) {
-//                Intent aIntent = new Intent(TestClient.this,
-//                                PresentationActivity.class);
-//                startActivity(aIntent);
-//            }
-//        });
-//
-//    }
-//
-//    private void enableButtons(boolean aEnabled) {
-//        mButtonNext.setEnabled(aEnabled);
-//        mButtonPrevious.setEnabled(aEnabled);
-//    }
-//
-//    class MessageHandler extends Handler {
-//        @Override
-//        public void handleMessage(Message aMessage) {
-//            Bundle aData = aMessage.getData();
-//            switch (aMessage.what) {
-//            case CommunicationService.MSG_SLIDE_CHANGED:
-//                int newSlide = aData.getInt("slide_number");
-//                mSlideLabel.setText("Slide " + newSlide);
-//                mCurrentPreviewImageMissing = true;
-//                // We continue on to try and update the image.
-//            case CommunicationService.MSG_SLIDE_PREVIEW:
-//                int aSlideNumber = aData.getInt("slide_number");
-//                if (mCurrentPreviewImageMissing) {
-//                    Bitmap aImage = mCommunicationService.getSlideShow()
-//                                    .getImage(aSlideNumber);
-//                    if (aImage != null) {
-//                        mImageView.setImageBitmap(aImage);
-//                        mCurrentPreviewImageMissing = false;
-//                    }
-//                }
-//                break;
-//
-//            }
-//        }
-//    }
-//}
-///* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java b/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java
index 148d31c..88f0da6 100644
--- a/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java
+++ b/android/sdremote/src/pl/polidea/coverflow/CoverFlow.java
@@ -39,350 +39,350 @@ import android.widget.SpinnerAdapter;
  */
 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 = -160;
-
-	/**
-	 * 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();
-		}
-	}
+    /**
+     * 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 = 30;
+
+    /**
+     * The maximum zoom on the centre Child.
+     */
+    private int mMaxZoom = -100;
+
+    /**
+     * 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


More information about the Libreoffice-commits mailing list