use of com.android.ide.common.rendering.api.ItemResourceValue in project kotlin by JetBrains.
the class LintUtils method getStyleAttributes.
/**
* Looks up the resource values for the given attribute given a style. Note that
* this only looks project-level style values, it does not resume into the framework
* styles.
*/
@Nullable
public static List<ResourceValue> getStyleAttributes(@NonNull Project project, @NonNull LintClient client, @NonNull String styleUrl, @NonNull String namespace, @NonNull String attribute) {
if (!client.supportsProjectResources()) {
return null;
}
AbstractResourceRepository resources = client.getProjectResources(project, true);
if (resources == null) {
return null;
}
ResourceUrl style = ResourceUrl.parse(styleUrl);
if (style == null || style.framework) {
return null;
}
List<ResourceValue> result = null;
Queue<ResourceValue> queue = new ArrayDeque<ResourceValue>();
queue.add(new ResourceValue(style.type, style.name, false));
Set<String> seen = Sets.newHashSet();
int count = 0;
boolean isFrameworkAttribute = ANDROID_URI.equals(namespace);
while (count < 30 && !queue.isEmpty()) {
ResourceValue front = queue.remove();
String name = front.getName();
seen.add(name);
List<ResourceItem> items = resources.getResourceItem(front.getResourceType(), name);
if (items != null) {
for (ResourceItem item : items) {
ResourceValue rv = item.getResourceValue(false);
if (rv instanceof StyleResourceValue) {
StyleResourceValue srv = (StyleResourceValue) rv;
ItemResourceValue value = srv.getItem(attribute, isFrameworkAttribute);
if (value != null) {
if (result == null) {
result = Lists.newArrayList();
}
if (!result.contains(value)) {
result.add(value);
}
}
String parent = srv.getParentStyle();
if (parent != null && !parent.startsWith(ANDROID_PREFIX)) {
ResourceUrl p = ResourceUrl.parse(parent);
if (p != null && !p.framework && !seen.contains(p.name)) {
seen.add(p.name);
queue.add(new ResourceValue(ResourceType.STYLE, p.name, false));
}
}
int index = name.lastIndexOf('.');
if (index > 0) {
String parentName = name.substring(0, index);
if (!seen.contains(parentName)) {
seen.add(parentName);
queue.add(new ResourceValue(ResourceType.STYLE, parentName, false));
}
}
}
}
}
count++;
}
return result;
}
use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.
the class ThemeEditorUtils method getGoodContrastPreviewBackground.
/**
* Returns the color that should be used for the background of the preview panel depending on the background color
* of the theme being displayed, so as to always keep some contrast between the two.
*/
public static JBColor getGoodContrastPreviewBackground(@NotNull ConfiguredThemeEditorStyle theme, @NotNull ResourceResolver resourceResolver) {
ItemResourceValue themeColorBackgroundItem = resolveItemFromParents(theme, "colorBackground", true);
ResourceValue backgroundResourceValue = resourceResolver.resolveResValue(themeColorBackgroundItem);
if (backgroundResourceValue != null) {
String colorBackgroundValue = backgroundResourceValue.getValue();
Color colorBackground = ResourceHelper.parseColor(colorBackgroundValue);
if (colorBackground != null) {
float backgroundDistance = MaterialColorUtils.colorDistance(colorBackground, ThemeEditorComponent.PREVIEW_BACKGROUND);
if (backgroundDistance < ThemeEditorComponent.COLOR_DISTANCE_THRESHOLD && backgroundDistance < MaterialColorUtils.colorDistance(colorBackground, ThemeEditorComponent.ALT_PREVIEW_BACKGROUND)) {
return ThemeEditorComponent.ALT_PREVIEW_BACKGROUND;
}
}
}
return ThemeEditorComponent.PREVIEW_BACKGROUND;
}
use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.
the class ThemeEditorUtils method getResourceDialog.
@NotNull
public static ChooseResourceDialog getResourceDialog(@NotNull EditedStyleItem item, @NotNull ThemeEditorContext context, EnumSet<ResourceType> allowedTypes) {
Module module = context.getModuleForResources();
ItemResourceValue itemSelectedValue = item.getSelectedValue();
String value = itemSelectedValue.getValue();
boolean isFrameworkValue = itemSelectedValue.isFramework();
String nameSuggestion = value;
ResourceUrl url = ResourceUrl.parse(value, isFrameworkValue);
if (url != null) {
nameSuggestion = url.name;
}
nameSuggestion = getDefaultResourceName(context, nameSuggestion);
ChooseResourceDialog.ResourceNameVisibility resourceNameVisibility = ChooseResourceDialog.ResourceNameVisibility.FORCE;
if (nameSuggestion.startsWith("#")) {
nameSuggestion = null;
resourceNameVisibility = ChooseResourceDialog.ResourceNameVisibility.SHOW;
}
ChooseResourceDialog dialog = ChooseResourceDialog.builder().setModule(module).setTypes(allowedTypes).setCurrentValue(value).setIsFrameworkValue(isFrameworkValue).setResourceNameVisibility(resourceNameVisibility).setResourceNameSuggestion(nameSuggestion).build();
dialog.setUseGlobalUndo(true);
return dialog;
}
use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.
the class ThemeAttributeResolver method resolveFromInheritance.
private void resolveFromInheritance(@NotNull ThemeEditorStyle themeEditorStyle, @NotNull FolderConfiguration configuration, @NotNull RestrictedConfiguration restricted, @NotNull Set<String> seenAttributes) {
RestrictedConfiguration styleRestricted = getRestrictedConfiguration(themeEditorStyle, configuration);
if (styleRestricted == null) {
LOG.warn(configuration + " is unreachable");
return;
}
styleRestricted = restricted.intersect(styleRestricted);
if (styleRestricted == null) {
return;
}
Set<String> newSeenAttributes = new HashSet<String>(seenAttributes);
for (ItemResourceValue item : themeEditorStyle.getValues(configuration)) {
String itemName = ResolutionUtils.getQualifiedItemName(item);
if (!newSeenAttributes.contains(itemName)) {
myItemValueMap.putValue(itemName, ConfiguredElement.create(styleRestricted.getAny(), item));
newSeenAttributes.add(itemName);
}
}
String parentName = themeEditorStyle.getParentName(configuration);
if (parentName == null) {
// We have reached the top of the theme hierarchy (i.e "android:Theme")
return;
}
ThemeEditorStyle parent = new ThemeEditorStyle(myManager, parentName);
for (FolderConfiguration folder : parent.getFolders()) {
resolveFromInheritance(parent, folder, styleRestricted, newSeenAttributes);
}
}
use of com.android.ide.common.rendering.api.ItemResourceValue in project android by JetBrains.
the class ThemeEditorComponent method createNewThemeWithAttributeValue.
/**
* Sets a new value to the passed attribute. It will also trigger the reload if a change happened.
* @param rv The attribute to set, including the current value.
* @param strValue The new value.
*/
private void createNewThemeWithAttributeValue(@NotNull final EditedStyleItem rv, @NotNull final String strValue) {
if (strValue.equals(rv.getValue())) {
// No modification required.
return;
}
ConfiguredThemeEditorStyle selectedStyle = getUsedStyle();
if (selectedStyle == null) {
LOG.error("No style/theme selected.");
return;
}
// The current style is R/O so we need to propagate this change a new style.
boolean isSubStyleSelected = isSubStyleSelected();
String message = String.format("<html>The %1$s '<code>%2$s</code>' is Read-Only.<br/>A new %1$s will be created to modify '<code>%3$s</code>'.<br/></html>", isSubStyleSelected ? "style" : "theme", selectedStyle.getQualifiedName(), rv.getName());
final ItemResourceValue originalValue = rv.getSelectedValue();
ParentRendererEditor.ThemeParentChangedListener themeListener = new ParentRendererEditor.ThemeParentChangedListener() {
private ConfiguredThemeEditorStyle myModifiedTheme;
@Override
public void themeChanged(@NotNull String name) {
if (myModifiedTheme != null) {
myModifiedTheme.getStyleResourceValue().addItem(originalValue);
}
myModifiedTheme = myThemeEditorContext.getThemeResolver().getTheme(name);
assert myModifiedTheme != null;
ItemResourceValue newSelectedValue = new ItemResourceValue(originalValue.getName(), originalValue.isFrameworkAttr(), strValue, false, null);
myModifiedTheme.getStyleResourceValue().addItem(newSelectedValue);
myPreviewThemeName = null;
refreshPreviewPanel(name);
}
@Override
public void reset() {
myModifiedTheme.getStyleResourceValue().addItem(originalValue);
reload(myThemeName);
}
};
final String newStyleName = ThemeEditorUtils.showCreateNewStyleDialog(selectedStyle, myThemeEditorContext, !isSubStyleSelected, false, message, isSubStyleSelected ? null : themeListener);
if (!isSubStyleSelected) {
themeListener.reset();
}
if (newStyleName == null) {
return;
}
// Need invokeLater to wait for the theme resolver to be aware of the newly created style through the resource change listener
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myThemeEditorContext.updateThemeResolver();
ConfiguredThemeEditorStyle newStyle = myThemeEditorContext.getThemeResolver().getTheme(newStyleName);
assert newStyle != null;
newStyle.setValue(rv.getQualifiedName(), strValue);
}
});
if (!isSubStyleSelected) {
// We changed a theme, so we are done.
// We don't need to call reload, because myResourceChangeListener will take care of it
myThemeName = newStyleName;
mySubStyleName = null;
return;
}
ConfiguredThemeEditorStyle selectedTheme = getSelectedTheme();
if (selectedTheme == null) {
LOG.error("No theme selected.");
return;
}
// Decide what property we need to modify.
// If the modified style was pointed by a theme attribute, we need to use that theme attribute value
// as property. Otherwise, just update the original property name with the new style.
final String sourcePropertyName = mySubStyleSourceAttribute.isAttr() ? mySubStyleSourceAttribute.getAttrPropertyName() : mySubStyleSourceAttribute.getQualifiedName();
// We've modified a sub-style so we need to modify the attribute that was originally pointing to this.
if (selectedTheme.isReadOnly()) {
// The theme pointing to the new style is r/o so create a new theme and then write the value.
message = String.format("<html>The style '%1$s' which references to '%2$s' is also Read-Only.<br/>" + "A new theme will be created to point to the modified style '%3$s'.<br/></html>", selectedTheme.getQualifiedName(), rv.getName(), newStyleName);
final String newThemeName = ThemeEditorUtils.showCreateNewStyleDialog(selectedTheme, myThemeEditorContext, true, false, message, themeListener);
themeListener.reset();
if (newThemeName != null) {
// We don't need to call reload, because myResourceChangeListener will take care of it
myThemeName = newThemeName;
mySubStyleName = newStyleName;
// Need invokeLater to wait for the theme resolver to be aware of the newly created theme through the resource change listener
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myThemeEditorContext.updateThemeResolver();
ConfiguredThemeEditorStyle newTheme = myThemeEditorContext.getThemeResolver().getTheme(newThemeName);
assert newTheme != null;
newTheme.setValue(sourcePropertyName, newStyleName);
}
});
}
} else {
selectedTheme.setValue(sourcePropertyName, newStyleName);
// We don't need to call reload, because myResourceChangeListener will take care of it
mySubStyleName = newStyleName;
}
}
Aggregations