use of com.android.resources.Density in project android by JetBrains.
the class ResourceResolverCache method replaceDrawableBitmaps.
/**
* Replaces drawable bitmaps with those from the real older target. This helps the simulated platform look more genuine,
* since a lot of the look comes from the nine patch assets. For example, when used to simulate Froyo, the checkboxes
* will look better than if we use the current classic theme assets, which look like gingerbread.
*/
private static void replaceDrawableBitmaps(@NotNull Map<ResourceType, ResourceValueMap> frameworkResources, @NotNull IAndroidTarget from, @NotNull IAndroidTarget realTarget) {
// This is a bit hacky; we should be operating at the resource repository level rather than
// for configured resources. However, we may not need this for very long.
ResourceValueMap map = frameworkResources.get(ResourceType.DRAWABLE);
String oldPrefix = from.getPath(IAndroidTarget.RESOURCES);
String newPrefix = realTarget.getPath(IAndroidTarget.RESOURCES);
if (map == null || map.isEmpty() || oldPrefix == null || newPrefix == null || oldPrefix.equals(newPrefix)) {
return;
}
Collection<ResourceValue> values = map.values();
Map<String, String> densityDirMap = Maps.newHashMap();
// Leave XML drawable resources alone since they can reference nonexistent colors and other resources
// not available in the real rendering platform
final boolean ONLY_REPLACE_BITMAPS = true;
Density[] densities = Density.values();
for (ResourceValue value : values) {
String v = value.getValue();
//noinspection ConstantConditions,PointlessBooleanExpression
if (v != null && (!ONLY_REPLACE_BITMAPS || v.endsWith(DOT_PNG))) {
if (v.startsWith(oldPrefix)) {
String relative = v.substring(oldPrefix.length());
if (v.endsWith(DOT_PNG)) {
int index = relative.indexOf(File.separatorChar);
if (index == -1) {
index = relative.indexOf('/');
}
if (index == -1) {
continue;
}
String parent = relative.substring(0, index);
String replace = densityDirMap.get(parent);
if (replace == null) {
FolderConfiguration configuration = FolderConfiguration.getConfigForFolder(parent);
if (configuration != null) {
DensityQualifier densityQualifier = configuration.getDensityQualifier();
if (densityQualifier != null) {
Density density = densityQualifier.getValue();
if (!new File(newPrefix, parent).exists()) {
String oldQualifier = SdkConstants.RES_QUALIFIER_SEP + density.getResourceValue();
String matched = null;
for (Density d : densities) {
if (d.ordinal() <= density.ordinal()) {
// No reason to check higher
continue;
}
String newQualifier = SdkConstants.RES_QUALIFIER_SEP + d.getResourceValue();
String newName = parent.replace(oldQualifier, newQualifier);
File dir = new File(newPrefix, newName);
if (dir.exists()) {
matched = newName;
break;
}
}
if (matched == null) {
continue;
}
replace = matched;
// This isn't right; there may be some assets only in mdpi!
densityDirMap.put(parent, replace);
}
}
}
}
relative = replace + relative.substring(index);
}
File newFile = new File(newPrefix, relative);
if (newFile.exists()) {
value.setValue(newFile.getPath());
}
}
}
}
}
use of com.android.resources.Density in project android by JetBrains.
the class VaryingConfiguration method getDevice.
@Override
@Nullable
public Device getDevice() {
if (isOverridingDevice()) {
return super.getDevice();
}
Device device = myParent.getDevice();
if (isAlternatingDevice() && device != null) {
if (device == myPrevParentDevice) {
return myPrevDevice;
}
myPrevParentDevice = device;
// Pick a different device
List<Device> devices = getConfigurationManager().getDevices();
// Divide up the available devices into {@link #myVariationCount} + 1 buckets
// (the + 1 is for the bucket now taken up by the inherited value).
// Then assign buckets to each {@link #myVariation} version, and pick one
// from the bucket assigned to this current configuration's variation version.
// I could just divide up the device list count, but that would treat a lot of
// very similar phones as having the same kind of variety as the 7" and 10"
// tablets which are sitting right next to each other in the device list.
// Instead, do this by screen size.
boolean isTv = isTv(device);
boolean isWear = isWear(device);
double smallest = 100;
double biggest = 1;
for (Device d : devices) {
double size = getScreenSize(d);
if (size < 0) {
// no data
continue;
} else if (isTv != isTv(d) || isWear != isWear(d)) {
continue;
}
if (size >= biggest) {
biggest = size;
}
if (size <= smallest) {
smallest = size;
}
}
int bucketCount = myVariationCount + 1;
double inchesPerBucket = (biggest - smallest) / bucketCount;
double overriddenSize = getScreenSize(device);
int overriddenBucket = (int) ((overriddenSize - smallest) / inchesPerBucket);
int bucket = (myVariation < overriddenBucket) ? myVariation : myVariation + 1;
double from = inchesPerBucket * bucket + smallest;
double to = from + inchesPerBucket;
if (biggest - to < 0.1) {
to = biggest + 0.1;
}
boolean canScaleNinePatch = supports(Features.FIXED_SCALABLE_NINE_PATCH);
for (Device d : devices) {
if (isTv != isTv(d) || isWear != isWear(d)) {
continue;
}
double size = getScreenSize(d);
if (size >= from && size < to) {
if (!canScaleNinePatch) {
Density density = getDensity(d);
if (density == null || !density.isRecommended() || density == Density.LOW) {
continue;
}
}
device = d;
break;
}
}
myPrevDevice = device;
}
return device;
}
use of com.android.resources.Density in project android by JetBrains.
the class ConfirmGenerateIconsStep method onEntering.
@Override
protected void onEntering() {
// Just in case we're entering this step a second time
myListeners.release(mySelectedSourceSet);
myListeners.receiveAndFire(mySelectedSourceSet, sourceSet -> {
AndroidIconGenerator iconGenerator = getModel().getIconGenerator();
File resDir = sourceSet.getPaths().getResDirectory();
if (iconGenerator == null || resDir == null || resDir.getParentFile() == null) {
return;
}
final Map<File, BufferedImage> pathIconMap = iconGenerator.generateIntoFileMap(sourceSet.getPaths());
myFilesAlreadyExist.set(false);
int minHeight = Integer.MAX_VALUE;
int maxHeight = Integer.MIN_VALUE;
for (BufferedImage image : pathIconMap.values()) {
minHeight = Math.min(minHeight, image.getHeight());
maxHeight = Math.max(maxHeight, image.getHeight());
}
ImmutableSortedSet.Builder<File> sortedPaths = ImmutableSortedSet.orderedBy(new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
String path1 = file1.getAbsolutePath();
String path2 = file2.getAbsolutePath();
Density density1 = CategoryIconMap.pathToDensity(path1);
Density density2 = CategoryIconMap.pathToDensity(path2);
if (density1 != null && density2 != null && density1 != density2) {
return Ints.compare(density2.ordinal(), density1.ordinal());
} else {
BufferedImage image1 = pathIconMap.get(file1);
BufferedImage image2 = pathIconMap.get(file2);
int compareValue = Ints.compare(image2.getHeight(), image1.getHeight());
return (compareValue != 0) ? compareValue : path2.compareTo(path1);
}
}
});
sortedPaths.addAll(pathIconMap.keySet());
FileTreeModel treeModel = new FileTreeModel(resDir.getParentFile(), true);
for (File path : sortedPaths.build()) {
Image image = pathIconMap.get(path);
if (path.exists()) {
myFilesAlreadyExist.set(true);
}
if (maxHeight > MAX_TREE_ROW_HEIGHT) {
int hCurr = image.getHeight(null);
int wCurr = image.getWidth(null);
double hScale;
if (maxHeight != minHeight) {
double hCurrPercent = (double) (hCurr - minHeight) / (double) (maxHeight - minHeight);
double scaledDeltaH = hCurrPercent * (MAX_TREE_ROW_HEIGHT - minHeight);
double hCurrScaled = minHeight + scaledDeltaH;
hScale = hCurrScaled / hCurr;
} else {
hScale = MAX_TREE_ROW_HEIGHT / (double) hCurr;
}
int hFinal = (int) (hCurr * hScale);
int wFinal = (int) (wCurr * hScale);
image = image.getScaledInstance(wFinal, hFinal, Image.SCALE_SMOOTH);
}
treeModel.forceAddFile(path, new ImageIcon(image));
}
myOutputPreviewTree.setModel(treeModel);
for (int i = 0; i < myOutputPreviewTree.getRowCount(); ++i) {
myOutputPreviewTree.expandRow(i);
}
});
}
use of com.android.resources.Density in project android by JetBrains.
the class CategoryIconMap method pathToDensity.
/**
* Convert the path to a density, if possible. Output paths don't always map cleanly to density
* values, such as the path for the "web" icon, so in those cases, {@code null} is returned.
*/
@Nullable
public static Density pathToDensity(@NotNull String iconPath) {
iconPath = FileUtil.toSystemIndependentName(iconPath);
// Strip off the filename, in case the user names their icon "xxxhdpi" etc.
// but leave the trailing slash, as it's used in the regex pattern
iconPath = iconPath.substring(0, iconPath.lastIndexOf('/') + 1);
for (Density density : Density.values()) {
if (DENSITY_PATTERNS.get(density).matcher(iconPath).matches()) {
return density;
}
}
return null;
}
use of com.android.resources.Density in project android by JetBrains.
the class PreviewIconsPanel method initializeIconComponents.
private void initializeIconComponents(@NotNull Collection<Density> densities) {
// Sort the densities, so that we always line up icons from highest to lowest densities.
Ordering<Density> densityOrdering = new Ordering<Density>() {
@Override
public int compare(Density left, Density right) {
// The lower the enum index, the higher the density
return Ints.compare(left.ordinal(), right.ordinal());
}
};
densities = densityOrdering.immutableSortedCopy(densities);
for (Density density : densities) {
JPanel iconPanel = new JPanel(new VerticalFlowLayout(false, false));
iconPanel.setBackground(myTheme.getMainColor());
iconPanel.setOpaque(myTheme != Theme.TRANSPARENT);
JBLabel title = new JBLabel(density.getResourceValue());
title.setForeground(myTheme.getAltColor());
iconPanel.add(title);
ImageComponent iconImage = new ImageComponent(null);
iconImage.setBorder(new LineBorder(myTheme.getAltColor()));
iconImage.setOpaque(false);
iconPanel.add(iconImage);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.PAGE_START;
myIconsPanel.add(iconPanel, c);
myIconImages.put(density, iconImage);
}
}
Aggregations