diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/mail/browse/ConversationItemView.java | 186 | ||||
-rw-r--r-- | src/com/android/mail/browse/ConversationItemViewCoordinates.java | 71 |
2 files changed, 130 insertions, 127 deletions
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java index 82cc8616e..effce31f6 100644 --- a/src/com/android/mail/browse/ConversationItemView.java +++ b/src/com/android/mail/browse/ConversationItemView.java @@ -94,7 +94,6 @@ import com.android.mail.utils.ViewUtils; import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -202,6 +201,9 @@ public class ConversationItemView extends View private int mGadgetMode; private static int sFoldersStartPadding; + private static int sFoldersInnerPadding; + private static int sFoldersMaxCount; + private static int sFoldersOverflowGradientPadding; private static TextAppearanceSpan sSubjectTextUnreadSpan; private static TextAppearanceSpan sSubjectTextReadSpan; private static TextAppearanceSpan sBadgeTextSpan; @@ -266,24 +268,89 @@ public class ConversationItemView extends View return mFoldersCount > 0; } - private int measureFolders(int availableSpace, int cellSize) { - int totalWidth = 0; - boolean firstTime = true; + /** + * Helper function to calculate exactly how much space the displayed folders should take. + * @return an array of integers that signifies the length in dp. + */ + private MeasurementWrapper measureFolderDimen(ConversationItemViewCoordinates coordinates) { + // This signifies the absolute max for each folder cell, no exceptions. + final int maxCellWidth = coordinates.folderCellWidth; + + final int numDisplayedFolders = Math.min(sFoldersMaxCount, mFoldersSortedSet.size()); + if (numDisplayedFolders == 0) { + return new MeasurementWrapper(new int[0], new boolean[0]); + } + + // This variable is calculated based on the number of folders we are displaying + final int maxAllowedCellSize = Math.min(maxCellWidth, (coordinates.folderLayoutWidth - + (numDisplayedFolders - 1) * sFoldersStartPadding) / numDisplayedFolders); + final int[] measurements = new int[numDisplayedFolders]; + final boolean[] overflow = new boolean[numDisplayedFolders]; + final MeasurementWrapper result = new MeasurementWrapper(measurements, overflow); + + int count = 0; + int missingWidth = 0; + int extraWidth = 0; for (Folder f : mFoldersSortedSet) { + if (count > numDisplayedFolders - 1) { + break; + } + final String folderString = f.name; - int width = (int) sFoldersPaint.measureText(folderString) + cellSize; - if (firstTime) { - firstTime = false; + final int neededWidth = (int) sFoldersPaint.measureText(folderString) + + 2 * sFoldersInnerPadding; + + if (neededWidth > maxAllowedCellSize) { + // What we can take from others is the minimum of the width we need to borrow + // and the width we are allowed to borrow. + final int borrowedWidth = Math.min(neededWidth - maxAllowedCellSize, + maxCellWidth - maxAllowedCellSize); + final int extraWidthLeftover = extraWidth - borrowedWidth; + if (extraWidthLeftover >= 0) { + measurements[count] = Math.min(neededWidth, maxCellWidth); + extraWidth = extraWidthLeftover; + } else { + measurements[count] = maxAllowedCellSize + extraWidth; + extraWidth = 0; + } + missingWidth = -extraWidthLeftover; + overflow[count] = neededWidth > measurements[count]; } else { - width += sFoldersStartPadding; - } - totalWidth += width; - if (totalWidth > availableSpace) { - break; + extraWidth = maxAllowedCellSize - neededWidth; + measurements[count] = neededWidth; + if (missingWidth > 0) { + if (extraWidth >= missingWidth) { + measurements[count - 1] += missingWidth; + extraWidth -= missingWidth; + overflow[count - 1] = false; + } else { + measurements[count - 1] += extraWidth; + extraWidth = 0; + } + } + missingWidth = 0; } + + count++; } - return totalWidth; + return result; + } + + /** + * @return how much total space the folders list requires. + */ + private int measureFolders(ConversationItemViewCoordinates coordinates) { + int[] sizes = measureFolderDimen(coordinates).measurements; + return sumWidth(sizes); + } + + private int sumWidth(int[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum + (arr.length - 1) * sFoldersStartPadding; } public void drawFolders( @@ -291,7 +358,11 @@ public class ConversationItemView extends View if (mFoldersCount == 0) { return; } - final int left = coordinates.foldersLeft; + + final MeasurementWrapper wrapper = measureFolderDimen(coordinates); + final int[] measurements = wrapper.measurements; + final boolean[] overflow = wrapper.overflow; + final int right = coordinates.foldersRight; final int y = coordinates.foldersY; final int height = coordinates.foldersHeight; @@ -301,75 +372,58 @@ public class ConversationItemView extends View sFoldersPaint.setTypeface(coordinates.foldersTypeface); // Initialize space and cell size based on the current mode. - int availableSpace = right - left; - int maxFoldersCount = availableSpace / coordinates.getFolderMinimumWidth(); - int foldersCount = Math.min(mFoldersCount, maxFoldersCount); - int averageWidth = availableSpace / foldersCount; - int cellSize = coordinates.getFolderCellWidth(); - - // TODO(ath): sFoldersPaint.measureText() is done 3x in this method. stop that. - // Extra credit: maybe cache results across items as long as font size doesn't change. - - final int totalWidth = measureFolders(availableSpace, cellSize); - int xLeft = (isRtl) ? left : right - Math.min(availableSpace, totalWidth); - final boolean overflow = totalWidth > availableSpace; - - // Second pass to draw folders. - int i = 0; - for (Iterator<Folder> it = isRtl ? - mFoldersSortedSet.descendingIterator() : mFoldersSortedSet.iterator(); - it.hasNext();) { - final Folder f = it.next(); - if (availableSpace <= 0) { + final int foldersCount = measurements.length; + final int width = sumWidth(measurements); + int xLeft = (isRtl) ? right - coordinates.folderLayoutWidth : right - width; + + int index = 0; + for (Folder f : mFoldersSortedSet) { + if (index > foldersCount - 1) { break; } + final String folderString = f.name; final int fgColor = f.getForegroundColor(mDefaultFgColor); final int bgColor = f.getBackgroundColor(mDefaultBgColor); - boolean labelTooLong = false; - final int textW = (int) sFoldersPaint.measureText(folderString); - int width = textW + cellSize + sFoldersStartPadding; - - if (overflow && width > averageWidth) { - if (i < foldersCount - 1) { - width = averageWidth; - } else { - // allow the last label to take all remaining space - // (and don't let it make room for padding) - width = availableSpace + sFoldersStartPadding; - } - labelTooLong = true; - } // Draw the box. sFoldersPaint.setColor(bgColor); sFoldersPaint.setStyle(Paint.Style.FILL); final RectF rect = - new RectF(xLeft, y, xLeft + width - sFoldersStartPadding, y + height); + new RectF(xLeft, y, xLeft + measurements[index], y + height); canvas.drawRoundRect(rect, sFolderRoundedCornerRadius, sFolderRoundedCornerRadius, sFoldersPaint); // Draw the text. - final int padding = cellSize / 2; sFoldersPaint.setColor(fgColor); sFoldersPaint.setStyle(Paint.Style.FILL); - if (labelTooLong) { - // todo - take RTL into account for fade - final int rightBorder = xLeft + width - sFoldersStartPadding - padding; - final Shader shader = new LinearGradient(rightBorder - padding, y, - rightBorder, y, fgColor, Utils.getTransparentColor(fgColor), - Shader.TileMode.CLAMP); + if (overflow[index]) { + final int rightBorder = xLeft + measurements[index]; + final int x0 = (isRtl) ? xLeft + sFoldersOverflowGradientPadding : + rightBorder - sFoldersOverflowGradientPadding; + final int x1 = (isRtl) ? xLeft + sFoldersInnerPadding : + rightBorder - sFoldersInnerPadding; + final Shader shader = new LinearGradient(x0, y, x1, y, fgColor, + Utils.getTransparentColor(fgColor), Shader.TileMode.CLAMP); sFoldersPaint.setShader(shader); } - canvas.drawText(folderString, xLeft + padding, y + height - textBottomPadding, - sFoldersPaint); - if (labelTooLong) { + canvas.drawText(folderString, xLeft + sFoldersInnerPadding, + y + height - textBottomPadding, sFoldersPaint); + if (overflow[index]) { sFoldersPaint.setShader(null); } - availableSpace -= width; - xLeft += width; - i++; + xLeft += measurements[index++] + sFoldersStartPadding; + } + } + + private static class MeasurementWrapper { + final int[] measurements; + final boolean[] overflow; + + public MeasurementWrapper(int[] m, boolean[] o) { + measurements = m; + overflow = o; } } } @@ -475,6 +529,10 @@ public class ConversationItemView extends View sElidedPaddingToken = res.getString(R.string.elided_padding_token); sScrollSlop = res.getInteger(R.integer.swipeScrollSlop); sFoldersStartPadding = res.getDimensionPixelOffset(R.dimen.folders_start_padding); + sFoldersInnerPadding = res.getDimensionPixelOffset(R.dimen.folder_cell_content_padding); + sFoldersMaxCount = res.getInteger(R.integer.conversation_list_max_folder_count); + sFoldersOverflowGradientPadding = + res.getDimensionPixelOffset(R.dimen.folders_gradient_padding); sCabAnimationDuration = res.getInteger(R.integer.conv_item_view_cab_anim_duration); sBadgePaddingExtraWidth = res.getDimensionPixelSize(R.dimen.badge_padding_extra_width); sBadgeRoundedCornerRadius = @@ -931,9 +989,7 @@ public class ConversationItemView extends View final Spannable displayedStringBuilder = new SpannableString(snippet); // measure the width of the folders which overlap the snippet view - final int availableFolderSpace = mCoordinates.foldersRight - mCoordinates.foldersLeft; - final int folderWidth = mHeader.folderDisplayer.measureFolders(availableFolderSpace, - mCoordinates.getFolderCellWidth()); + final int folderWidth = mHeader.folderDisplayer.measureFolders(mCoordinates); // size the snippet view by subtracting the folder width from the maximum snippet width final int snippetWidth = mCoordinates.maxSnippetWidth - folderWidth; diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java index b89e425d6..fc1bea0fb 100644 --- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java +++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java @@ -58,10 +58,6 @@ public class ConversationItemViewCoordinates { static final int GADGET_CONTACT_PHOTO = 1; static final int GADGET_CHECKBOX = 2; - // For combined views - private static int COLOR_BLOCK_WIDTH = -1; - private static int COLOR_BLOCK_HEIGHT = -1; - /** * Simple holder class for an item's abstract configuration state. ListView binding creates an * instance per item, and {@link #forConfig(Context, Config, CoordinatesCache)} uses it to @@ -223,6 +219,8 @@ public class ConversationItemViewCoordinates { final float snippetFontSize; // Folders. + final int folderLayoutWidth; + final int folderCellWidth; final int foldersLeft; final int foldersRight; final int foldersY; @@ -266,28 +264,17 @@ public class ConversationItemViewCoordinates { final int contactImagesX; final int contactImagesY; + /** * The smallest item width for which we use the "wide" layout. */ private final int mMinListWidthForWide; - /** - * The smallest item width for which we use the "spacious" variant of the normal layout, - * if the normal version is used at all. Larger than {@link #mMinListWidthForWide}, we use - * wide mode anyway, and this value is unused. - */ - private final int mMinListWidthIsSpacious; - private final int mFolderCellWidth; - private final int mFolderMinimumWidth; private ConversationItemViewCoordinates(final Context context, final Config config, final CoordinatesCache cache) { Utils.traceBeginSection("CIV coordinates constructor"); final Resources res = context.getResources(); - mFolderCellWidth = res.getDimensionPixelSize(R.dimen.folder_cell_width); mMinListWidthForWide = res.getDimensionPixelSize(R.dimen.list_min_width_is_wide); - mMinListWidthIsSpacious = res.getDimensionPixelSize( - R.dimen.list_normal_mode_min_width_is_spacious); - mFolderMinimumWidth = res.getDimensionPixelSize(R.dimen.folder_minimum_width); mMode = calculateMode(res, config); @@ -336,6 +323,12 @@ public class ConversationItemViewCoordinates { view.measure(widthSpec, heightSpec); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + // Once the view is measured, let's calculate the dynamic width variables. + folderLayoutWidth = (int) (view.getWidth() * + res.getInteger(R.integer.folder_max_width_proportion) / 100.0); + folderCellWidth = (int) (view.getWidth() * + res.getInteger(R.integer.folder_cell_max_width_proportion) / 100.0); + // Utils.dumpViewTree((ViewGroup) view); // Records coordinates. @@ -534,35 +527,6 @@ public class ConversationItemViewCoordinates { } } - @Deprecated - public static int getColorBlockWidth(Context context) { - Resources res = context.getResources(); - if (COLOR_BLOCK_WIDTH <= 0) { - COLOR_BLOCK_WIDTH = res.getDimensionPixelSize(R.dimen.color_block_width); - } - return COLOR_BLOCK_WIDTH; - } - - @Deprecated - public static int getColorBlockHeight(Context context) { - Resources res = context.getResources(); - if (COLOR_BLOCK_HEIGHT <= 0) { - COLOR_BLOCK_HEIGHT = res.getDimensionPixelSize(R.dimen.color_block_height); - } - return COLOR_BLOCK_HEIGHT; - } - - public static boolean displaySendersInline(int mode) { - switch (mode) { - case WIDE_MODE: - return false; - case NORMAL_MODE: - return true; - default: - throw new IllegalArgumentException("Unknown conversation header view mode " + mode); - } - } - /** * Returns coordinates for elements inside a conversation header view given * the view width. @@ -579,21 +543,4 @@ public class ConversationItemViewCoordinates { cache.put(cacheKey, coordinates); return coordinates; } - - /** - * Return the minimum width of a folder cell with no text. Essentially this is the left+right - * intra-cell margin within cells. - * - */ - public int getFolderCellWidth() { - return mFolderCellWidth; - } - - /** - * Return the minimum width of a folder cell, period. This will affect the - * maximum number of folders we can display. - */ - public int getFolderMinimumWidth() { - return mFolderMinimumWidth; - } } |