/*
* Copyright (C) 2011 The original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.zapta.apps.maniana.widget;
import static com.zapta.apps.maniana.util.Assertions.checkNotNull;
import com.zapta.apps.maniana.R;
import com.zapta.apps.maniana.annotations.ApplicationScope;
import com.zapta.apps.maniana.util.LogUtil;
/**
* Descriptor of a paper background bitmap resource. For technical reasons, the paper background
* bitmap size in pixels must be smaller than the rendered list widget template bitmap, otherwise
* the ImageView is stretched to accommodate the background paper. For this reason, we use a set of
* paper images of different sizes and pick dynamically the best fit.
*
* @author Tal Dayan
*/
@ApplicationScope
public class PaperBackground {
private static final PaperBackground PAPER_BACKGROUNDS[] = new PaperBackground[] {
new PaperBackground(R.drawable.widget_paper_104x114, 104, 114, 4),
new PaperBackground(R.drawable.widget_paper_300x064, 300, 64, 4),
new PaperBackground(R.drawable.widget_paper_304x194, 304, 194, 4),
new PaperBackground(R.drawable.widget_paper_304x282, 304, 382, 4)
};
public final int drawableResourceId;
public final int widthPixels;
public final int heightPixels;
/** The width of the drop shadow on right and bottom margins. */
public final int shadowPixels;
private PaperBackground(int drawableResourceId, int widthPixels, int heightPixels, int shadowPixels) {
this.drawableResourceId = drawableResourceId;
this.widthPixels = widthPixels;
this.heightPixels = heightPixels;
this.shadowPixels = shadowPixels;
}
public final int shadowRightPixels(int strechedWidthPixels) {
// TODO: round the result?
return (shadowPixels * strechedWidthPixels) / widthPixels;
}
public final int shadowBottomPixels(int strechedHeightPixels) {
// TODO: round the result?
return (shadowPixels * strechedHeightPixels) / heightPixels;
}
/**
* Return fitness metric of this paper for given widget size.
*
* @return merit metrics. Higher values are preferred over lower values. May be negative. Actual
* value is meanigless. Should be used for comparison only
*/
private final int merit(int widthPixels, int heightPixels) {
final boolean fits = (this.widthPixels <= widthPixels)
&& (this.heightPixels <= heightPixels);
int result = 0;
if (fits) {
// Prefers backgrounds with larger areas
result += (this.widthPixels * this.heightPixels);
} else {
// Prefer backgrounds with minimal extra dimension.
result -= Math.max(0, this.widthPixels - widthPixels);
result -= Math.max(0, this.heightPixels - heightPixels);
}
return result;
}
static final PaperBackground getBestSize(int widthPixels, int heightPixels) {
PaperBackground bestResult = null;
int bestMerit = 0;
for (PaperBackground iter : PAPER_BACKGROUNDS) {
final int iterMerit = iter.merit(widthPixels, heightPixels);
if (bestResult == null || iterMerit > bestMerit) {
bestResult = iter;
bestMerit = iterMerit;
}
}
// Should not fail since we have at least one background and we always set it
// on the first iteration.
checkNotNull(bestResult, "No paper matched %d x %d", widthPixels, heightPixels);
if (bestResult.widthPixels > widthPixels
|| bestResult.heightPixels > heightPixels) {
LogUtil.error("Paper background does not fit: %d x %s -> %d x %d", widthPixels,
heightPixels, bestResult.widthPixels, bestResult.heightPixels);
}
return bestResult;
}
}