Provides more control over detail alignment.
Replaces setDrawDetailsBelowCard and setDetailTexturesCentered
with setDetailTextureAlignment, and implements support for
vertical centering.
Change-Id: Idee5f28235e269667132920421cfe32f91456285
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 139ba14..7631948 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -17,6 +17,7 @@
package com.android.ex.carousel;
import com.android.ex.carousel.CarouselRS.CarouselCallback;
+import com.android.ex.carousel.MVCCarouselView.DetailAlignment;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -43,6 +44,8 @@
private final float DEFAULT_SWAY_SENSITIVITY = 0.0f;
private final float DEFAULT_FRICTION_COEFFICIENT = 10.0f;
private final float DEFAULT_DRAG_FACTOR = 0.25f;
+ private final int DEFAULT_DETAIL_ALIGNMENT =
+ DetailAlignment.VIEW_TOP | DetailAlignment.LEFT;
private CarouselRS mRenderScript;
private RenderScriptGL mRS;
private static final String TAG = "CarouselController";
@@ -62,8 +65,7 @@
private int mVisibleSlots = 0;
private int mVisibleDetails = DEFAULT_VISIBLE_DETAIL_COUNT;
private int mPrefetchCardCount = DEFAULT_PREFETCH_CARD_COUNT;
- private boolean mDrawDetailBelowCard = false;
- private boolean mDetailTexturesCentered = false;
+ private int mDetailTextureAlignment = DEFAULT_DETAIL_ALIGNMENT;
private boolean mDrawCardsWithBlending = true;
private boolean mDrawRuler = true;
private float mStartAngle;
@@ -100,7 +102,7 @@
setVisibleSlots(mVisibleSlots);
setVisibleDetails(mVisibleDetails);
setPrefetchCardCount(mPrefetchCardCount);
- setDrawDetailBelowCard(mDrawDetailBelowCard);
+ setDetailTextureAlignment(mDetailTextureAlignment);
setDrawRuler(mDrawRuler);
setCallback(mCarouselCallback);
setDefaultBitmap(mDefaultBitmap);
@@ -205,27 +207,25 @@
}
/**
- * Set whether to draw the detail texture above or below the card.
+ * Sets how detail textures are aligned with respect to the card.
*
- * @param below False for above, true for below.
+ * @param alignment a bitmask of DetailAlignment flags.
*/
- public void setDrawDetailBelowCard(boolean below) {
- mDrawDetailBelowCard = below;
- if (mRenderScript != null) {
- mRenderScript.setDrawDetailBelowCard(below);
+ public void setDetailTextureAlignment(int alignment) {
+ int xBits = alignment & DetailAlignment.HORIZONTAL_ALIGNMENT_MASK;
+ if (xBits == 0 || ((xBits & (xBits - 1)) != 0)) {
+ throw new IllegalArgumentException(
+ "Must specify exactly one horizontal alignment flag");
}
- }
+ int yBits = alignment & DetailAlignment.VERTICAL_ALIGNMENT_MASK;
+ if (yBits == 0 || ((yBits & (yBits - 1)) != 0)) {
+ throw new IllegalArgumentException(
+ "Must specify exactly one vertical alignment flag");
+ }
- /**
- * Set whether to align the detail texture center with the card center.
- * If not, left edges will be aligned instead.
- *
- * @param centered True for center-aligned, false for left-aligned.
- */
- public void setDetailTexturesCentered(boolean centered) {
- mDetailTexturesCentered = centered;
+ mDetailTextureAlignment = alignment;
if (mRenderScript != null) {
- mRenderScript.setDetailTexturesCentered(centered);
+ mRenderScript.setDetailTextureAlignment(alignment);
}
}
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index 6f62bb6..efa6ff6 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -367,13 +367,8 @@
mScript.set_prefetchCardCount(count);
}
-
- public void setDrawDetailBelowCard(boolean below) {
- mScript.set_drawDetailBelowCard(below);
- }
-
- public void setDetailTexturesCentered(boolean centered) {
- mScript.set_detailTexturesCentered(centered);
+ public void setDetailTextureAlignment(int alignment) {
+ mScript.set_detailTextureAlignment(alignment);
}
public void setDrawCardsWithBlending(boolean enabled) {
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 062f250..0b6bc3f 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -51,6 +51,8 @@
private final float DEFAULT_SWAY_SENSITIVITY = 0.0f;
private final float DEFAULT_FRICTION_COEFFICIENT = 10.0f;
private final float DEFAULT_DRAG_FACTOR = 0.25f;
+ private final int DEFAULT_DETAIL_ALIGNMENT =
+ DetailAlignment.VIEW_TOP | DetailAlignment.LEFT;
private static final String TAG = "CarouselView";
private static final boolean DBG = false;
private CarouselRS mRenderScript;
@@ -71,8 +73,7 @@
private int mVisibleSlots = 0;
private int mVisibleDetails = DEFAULT_VISIBLE_DETAIL_COUNT;
private int mPrefetchCardCount = DEFAULT_PREFETCH_CARD_COUNT;
- private boolean mDrawDetailBelowCard = false;
- private boolean mDetailTexturesCentered = false;
+ private int mDetailTextureAlignment = DEFAULT_DETAIL_ALIGNMENT;
private boolean mDrawCardsWithBlending = true;
private boolean mDrawRuler = true;
private float mStartAngle;
@@ -94,6 +95,41 @@
private Bitmap mDetailLoadingBitmap = Bitmap.createBitmap(
new int[] {0}, 0, 1, 1, 1, Bitmap.Config.ARGB_4444);
+ // Note: remember to update carousel.rs when changing the values below
+ public static class DetailAlignment {
+ /** Detail is centered vertically with respect to the card **/
+ public static final int CENTER_VERTICAL = 1;
+ /** Detail is aligned with the top edge of the carousel view **/
+ public static final int VIEW_TOP = 1 << 1;
+ /** Detail is aligned with the bottom edge of the carousel view (not yet implemented) **/
+ public static final int VIEW_BOTTOM = 1 << 2;
+ /** Detail is positioned above the card (not yet implemented) **/
+ public static final int ABOVE = 1 << 3;
+ /** Detail is positioned below the card **/
+ public static final int BELOW = 1 << 4;
+ /** Mask that selects those bits that control vertical alignment **/
+ public static final int VERTICAL_ALIGNMENT_MASK = 0xff;
+
+ /**
+ * Detail is centered horizontally with respect to either the top or bottom
+ * extent of the card, depending on whether the detail is above or below the card.
+ */
+ public static final int CENTER_HORIZONTAL = 1 << 8;
+ /**
+ * Detail is aligned with the left edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ */
+ public static final int LEFT = 1 << 9;
+ /**
+ * Detail is aligned with the right edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ * (not yet implemented)
+ */
+ public static final int RIGHT = 1 << 10;
+ /** Mask that selects those bits that control horizontal alignment **/
+ public static final int HORIZONTAL_ALIGNMENT_MASK = 0xff00;
+ }
+
public static class Info {
public Info(int _resId) { resId = _resId; }
public int resId; // resource for renderscript resource (e.g. R.raw.carousel)
@@ -149,7 +185,7 @@
setVisibleSlots(mVisibleSlots);
setVisibleDetails(mVisibleDetails);
setPrefetchCardCount(mPrefetchCardCount);
- setDrawDetailBelowCard(mDrawDetailBelowCard);
+ setDetailTextureAlignment(mDetailTextureAlignment);
setDrawRuler(mDrawRuler);
setCallback(mCarouselCallback);
setDefaultBitmap(mDefaultBitmap);
@@ -267,27 +303,25 @@
}
/**
- * Set whether to draw the detail texture above or below the card.
+ * Sets how detail textures are aligned with respect to the card.
*
- * @param below False for above, true for below.
+ * @param alignment a bitmask of DetailAlignment flags.
*/
- public void setDrawDetailBelowCard(boolean below) {
- mDrawDetailBelowCard = below;
- if (mRenderScript != null) {
- mRenderScript.setDrawDetailBelowCard(below);
+ public void setDetailTextureAlignment(int alignment) {
+ int xBits = alignment & DetailAlignment.HORIZONTAL_ALIGNMENT_MASK;
+ if (xBits == 0 || ((xBits & (xBits - 1)) != 0)) {
+ throw new IllegalArgumentException(
+ "Must specify exactly one horizontal alignment flag");
}
- }
+ int yBits = alignment & DetailAlignment.VERTICAL_ALIGNMENT_MASK;
+ if (yBits == 0 || ((yBits & (yBits - 1)) != 0)) {
+ throw new IllegalArgumentException(
+ "Must specify exactly one vertical alignment flag");
+ }
- /**
- * Set whether to align the detail texture center with the card center.
- * If not, left edges will be aligned instead.
- *
- * @param centered True for center-aligned, false for left-aligned.
- */
- public void setDetailTexturesCentered(boolean centered) {
- mDetailTexturesCentered = centered;
+ mDetailTextureAlignment = alignment;
if (mRenderScript != null) {
- mRenderScript.setDetailTexturesCentered(centered);
+ mRenderScript.setDetailTextureAlignment(alignment);
}
}
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselView.java b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
index 5d7573d..abbf32a 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselView.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
@@ -53,6 +53,41 @@
CarouselController mController;
+ // Note: remember to update carousel.rs when changing the values below
+ public static class DetailAlignment {
+ /** Detail is centered vertically with respect to the card **/
+ public static final int CENTER_VERTICAL = 1;
+ /** Detail is aligned with the top edge of the carousel view **/
+ public static final int VIEW_TOP = 1 << 1;
+ /** Detail is aligned with the bottom edge of the carousel view (not yet implemented) **/
+ public static final int VIEW_BOTTOM = 1 << 2;
+ /** Detail is positioned above the card (not yet implemented) **/
+ public static final int ABOVE = 1 << 3;
+ /** Detail is positioned below the card **/
+ public static final int BELOW = 1 << 4;
+ /** Mask that selects those bits that control vertical alignment **/
+ public static final int VERTICAL_ALIGNMENT_MASK = 0xff;
+
+ /**
+ * Detail is centered horizontally with respect to either the top or bottom
+ * extent of the card, depending on whether the detail is above or below the card.
+ */
+ public static final int CENTER_HORIZONTAL = 1 << 8;
+ /**
+ * Detail is aligned with the left edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ */
+ public static final int LEFT = 1 << 9;
+ /**
+ * Detail is aligned with the right edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ * (not yet implemented)
+ */
+ public static final int RIGHT = 1 << 10;
+ /** Mask that selects those bits that control horizontal alignment **/
+ public static final int HORIZONTAL_ALIGNMENT_MASK = 0xff00;
+ }
+
public static class Info {
public Info(int _resId) { resId = _resId; }
public int resId; // resource for renderscript resource (e.g. R.raw.carousel)
@@ -198,22 +233,12 @@
}
/**
- * Set whether to draw the detail texture above or below the card.
- *
- * @param below False for above, true for below.
+ * Sets how detail textures are aligned with respect to the card.
+ *
+ * @param alignment a bitmask of DetailAlignment flags.
*/
- public void setDrawDetailBelowCard(boolean below) {
- mController.setDrawDetailBelowCard(below);
- }
-
- /**
- * Set whether to align the detail texture center with the card center.
- * If not, left edges will be aligned instead.
- *
- * @param centered True for center-aligned, false for left-aligned.
- */
- public void setDetailTexturesCentered(boolean centered) {
- mController.setDetailTexturesCentered(centered);
+ public void setDetailTextureAlignment(int alignment) {
+ mController.setDetailTextureAlignment(alignment);
}
/**
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 27fd522..9b38a5e 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -74,6 +74,41 @@
STATE_LOADED // item was delivered
};
+// Detail texture alignments ** THIS LIST MUST MATCH THOSE IN CarouselView.java ***
+enum {
+ /** Detail is centered vertically with respect to the card **/
+ CENTER_VERTICAL = 1,
+ /** Detail is aligned with the top edge of the carousel view **/
+ VIEW_TOP = 1 << 1,
+ /** Detail is aligned with the bottom edge of the carousel view (not yet implemented) **/
+ VIEW_BOTTOM = 1 << 2,
+ /** Detail is positioned above the card (not yet implemented) **/
+ ABOVE = 1 << 3,
+ /** Detail is positioned below the card **/
+ BELOW = 1 << 4,
+ /** Mask that selects those bits that control vertical alignment **/
+ VERTICAL_ALIGNMENT_MASK = 0xff,
+
+ /**
+ * Detail is centered horizontally with respect to either the top or bottom
+ * extent of the card, depending on whether the detail is above or below the card.
+ */
+ CENTER_HORIZONTAL = 1 << 8,
+ /**
+ * Detail is aligned with the left edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ */
+ LEFT = 1 << 9,
+ /**
+ * Detail is aligned with the right edge of either the top or the bottom of
+ * the card, depending on whether the detail is above or below the card.
+ * (not yet implemented)
+ */
+ RIGHT = 1 << 10,
+ /** Mask that selects those bits that control horizontal alignment **/
+ HORIZONTAL_ALIGNMENT_MASK = 0xff00,
+};
+
// Client messages *** THIS LIST MUST MATCH THOSE IN CarouselRS.java. ***
static const int CMD_CARD_SELECTED = 100;
static const int CMD_CARD_LONGPRESS = 110;
@@ -111,9 +146,7 @@
int visibleSlotCount; // number of visible slots (for culling)
int visibleDetailCount; // number of visible detail textures to show
int prefetchCardCount; // how many cards to keep in memory
-bool drawDetailBelowCard; // whether detail goes above (false) or below (true) the card
-// TODO(jshuma): Replace detailTexturesCentered with a detailTextureAlignment mode enum
-bool detailTexturesCentered; // line up detail center and card center (instead of left edges)
+int detailTextureAlignment; // How to align detail texture with respect to card
bool drawCardsWithBlending; // Enable blending while drawing cards (for translucent card textures)
bool drawRuler; // whether to draw a ruler from the card to the detail texture
float radius; // carousel radius. Cards will be centered on a circle with this radius
@@ -596,7 +629,7 @@
/*
* Draws a screen-aligned card with the exact dimensions from the detail texture.
- * This is used to display information about the object being displayed above the geomertry.
+ * This is used to display information about the object being displayed.
* Returns true if we're still animating any property of the cards (e.g. fades).
*/
static bool drawDetails(int64_t currentTime)
@@ -638,7 +671,7 @@
int indexLeft, indexRight;
float4 screenCoord;
- if (drawDetailBelowCard) {
+ if (detailTextureAlignment & BELOW) {
indexLeft = 0;
indexRight = 1;
} else {
@@ -652,6 +685,20 @@
rsDebug("Bad transform: ", screenCoord);
continue;
}
+ if (detailTextureAlignment & CENTER_VERTICAL) {
+ // If we're centering vertically, we'll need the other vertices too
+ if (detailTextureAlignment & BELOW) {
+ indexLeft = 3;
+ indexRight = 2;
+ } else {
+ indexLeft = 0;
+ indexRight = 1;
+ }
+ float4 otherScreenLeft = rsMatrixMultiply(&matrix, cardVertices[indexLeft]);
+ float4 otherScreenRight = rsMatrixMultiply(&matrix, cardVertices[indexRight]);
+ screenCoordRight.y = screenCoordLeft.y = (screenCoordLeft.y + screenCoordRight.y
+ + otherScreenLeft.y + otherScreenRight.y) / 4.;
+ }
(void) convertNormalizedToPixelCoordinates(&screenCoordLeft, width, height);
(void) convertNormalizedToPixelCoordinates(&screenCoordRight, width, height);
if (debugDetails) {
@@ -659,10 +706,12 @@
RS_DEBUG(screenCoordRight);
}
screenCoord = screenCoordLeft;
- if (drawDetailBelowCard) {
+ if (detailTextureAlignment & BELOW) {
screenCoord.y = min(screenCoordLeft.y, screenCoordRight.y);
+ } else if (detailTextureAlignment & CENTER_VERTICAL) {
+ screenCoord.y -= rsAllocationGetDimY(cards[i].detailTexture) / 2.;
}
- if (detailTexturesCentered) {
+ if (detailTextureAlignment & CENTER_HORIZONTAL) {
screenCoord.x += (screenCoordRight.x - screenCoordLeft.x) / 2. -
rsAllocationGetDimX(cards[i].detailTexture) / 2.;
}
@@ -693,11 +742,21 @@
shaderConstants->fadeAmount = blendedAlpha;
rsAllocationMarkDirty(rsGetAllocation(shaderConstants));
- // Draw line from upper left card corner to the top of the screen
+ // Draw line from the card to the detail texture.
+ // The line is drawn from the top or bottom left of the card
+ // to either the top of the screen or the top of the detail
+ // texture, depending on detailTextureAlignment.
if (drawRuler) {
+ float rulerTop;
+ float rulerBottom;
+ if (detailTextureAlignment & BELOW) {
+ rulerTop = screenCoord.y;
+ rulerBottom = 0;
+ } else {
+ rulerTop = height;
+ rulerBottom = screenCoord.y;
+ }
const float halfWidth = lineWidth * 0.5f;
- const float rulerTop = drawDetailBelowCard ? screenCoord.y : height;
- const float rulerBottom = drawDetailBelowCard ? 0 : screenCoord.y;
const float x0 = cards[i].detailLineOffset.x + screenCoord.x - halfWidth;
const float x1 = cards[i].detailLineOffset.x + screenCoord.x + halfWidth;
const float y0 = rulerBottom + yPadding;
@@ -717,7 +776,8 @@
const float textureHeight = rsAllocationGetDimY(cards[i].detailTexture);
const float offx = cards[i].detailTextureOffset.x;
const float offy = -cards[i].detailTextureOffset.y;
- const float textureTop = drawDetailBelowCard ? screenCoord.y : height;
+ const float textureTop = (detailTextureAlignment & VIEW_TOP)
+ ? height : screenCoord.y;
const float x0 = cards[i].detailLineOffset.x + screenCoord.x + offx;
const float x1 = cards[i].detailLineOffset.x + screenCoord.x + offx + textureWidth;
const float y0 = textureTop + offy - textureHeight - cards[i].detailLineOffset.y;