import org.eclipse.swt.widgets.ScrollBar;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* The accordion control allows a series of labels with associated content that can be
* @param greedy if true, grow vertically as much as possible
* @param wrapChildren if true, configure the child area to be horizontally laid out
* with wrapping
+ * @param expand Set of headers to expand initially
*/
public AccordionControl(Composite parent, int style, List<?> headers,
- boolean greedy, boolean wrapChildren) {
+ boolean greedy, boolean wrapChildren, Set<String> expand) {
super(parent, style);
mWrap = wrapChildren;
mOpen = IconFactory.getInstance().getIcon("open-folder"); //$NON-NLS-1$
mClosed = IconFactory.getInstance().getIcon("closed-folder"); //$NON-NLS-1$
- CLabel first = null;
+ List<CLabel> expandLabels = new ArrayList<CLabel>();
for (Object header : headers) {
final CLabel label = new CLabel(this, SWT.SHADOW_OUT);
}
updateIcon(label);
- if (first == null) {
- first = label;
+ if (expand != null && expand.contains(label.getText())) {
+ // Comparing "label.getText()" rather than "header" because we make some
+ // tweaks to the label (replacing & with && etc) and in the getExpandedCategories
+ // method we return the label texts
+ expandLabels.add(label);
}
}
- // Initially show the first category
- if (headers.size() > 0) {
- toggle(first, false, false);
+ // Expand the requested categories
+ for (CLabel label : expandLabels) {
+ toggle(label, false, false);
}
}
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
+
+ /**
+ * Returns the set of expanded categories in the palette. Note: Header labels will have
+ * escaped ampersand characters with double ampersands.
+ *
+ * @return the set of expanded categories in the palette - never null
+ */
+ public Set<String> getExpandedCategories() {
+ Set<String> expanded = new HashSet<String>();
+ for (Control c : getChildren()) {
+ if (c instanceof CLabel) {
+ if (isOpen(c)) {
+ expanded.add(((CLabel) c).getText());
+ }
+ }
+ }
+
+ return expanded;
+ }
}
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.StaticRenderSession;
import com.android.ide.common.rendering.api.Capability;
+import com.android.ide.common.rendering.api.DrawableParams;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderSession;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
* @param height the height to use for the layout, or -1 to use the height of the screen
* associated with this editor
* @param explodeNodes a set of nodes to explode, or null for none
- * @param transparentBackground If true, the rendering will <b>not</b> paint the
- * normal background requested by the theme, and it will instead paint the
- * background using a fully transparent background color
+ * @param overrideBgColor If non-null, use the given color as a background to render over
+ * rather than the normal background requested by the theme
+ * @param noDecor If true, don't draw window decorations like the system bar
* @param logger a logger where rendering errors are reported
* @param renderingMode the {@link RenderingMode} to use for rendering
* @return the resulting rendered image wrapped in an {@link RenderSession}
*/
public RenderSession render(UiDocumentNode model, int width, int height,
- Set<UiElementNode> explodeNodes, boolean transparentBackground,
+ Set<UiElementNode> explodeNodes, Integer overrideBgColor, boolean noDecor,
LayoutLog logger, RenderingMode renderingMode) {
if (!ensureFileValid()) {
return null;
IProject iProject = mEditedFile.getProject();
return renderWithBridge(iProject, model, layoutLib, width, height, explodeNodes,
- transparentBackground, logger, null /* includeWithin */, renderingMode);
+ overrideBgColor, noDecor, logger, null /* includeWithin */, renderingMode);
}
/**
}
RenderSession session = renderWithBridge(iProject, model, layoutLib, width, height,
- explodeNodes, false, logger, mIncludedWithin, renderingMode);
+ explodeNodes, null /*custom background*/, false /*no decorations*/, logger,
+ mIncludedWithin, renderingMode);
canvas.setSession(session, explodeNodes);
private RenderSession renderWithBridge(IProject iProject, UiDocumentNode model,
LayoutLibrary layoutLib, int width, int height, Set<UiElementNode> explodeNodes,
- boolean transparentBackground, LayoutLog logger, Reference includeWithin,
+ Integer overrideBgColor, boolean noDecor, LayoutLog logger, Reference includeWithin,
RenderingMode renderingMode) {
ResourceManager resManager = ResourceManager.getInstance();
mMinSdkVersion,
mTargetSdkVersion,
logger);
+ if (noDecor) {
+ params.setForceNoDecor();
+ }
// FIXME make persistent and only reload when the manifest (or at least resources) chanage.
IFolderWrapper projectFolder = new IFolderWrapper(getProject());
params.setConfigScreenSize(ssq.getValue());
}
- if (transparentBackground) {
- // It doesn't matter what the background color is as long as the alpha
- // is 0 (fully transparent). We're using red to make it more obvious if
- // for some reason the background is painted when it shouldn't be.
- params.setOverrideBgColor(0x00FF0000);
+ if (overrideBgColor != null) {
+ params.setOverrideBgColor(overrideBgColor.intValue());
}
// set the Image Overlay as the image factory.
}
}
+ /**
+ * Renders the given resource which should refer to a drawable and returns it
+ * as an image
+ *
+ * @param itemName the theme item to be looked up and rendered
+ * @param width the width of the drawable to be rendered
+ * @param height the height of the drawable to be rendered
+ * @return the image, or null if something went wrong
+ */
+ BufferedImage renderThemeItem(String itemName, int width, int height) {
+ ResourceResolver resources = createResolver();
+ LayoutLibrary layoutLibrary = getLayoutLibrary();
+ IProject project = getProject();
+ ResourceValue drawableResourceValue = resources.findItemInTheme(itemName);
+ Density density = mConfigComposite.getDensity();
+ float xdpi = mConfigComposite.getXDpi();
+ float ydpi = mConfigComposite.getYDpi();
+ ResourceManager resManager = ResourceManager.getInstance();
+ ProjectResources projectRes = resManager.getProjectResources(project);
+ ProjectCallback projectCallback = new ProjectCallback(
+ layoutLibrary.getClassLoader(), projectRes, project);
+ LayoutLog silentLogger = new LayoutLog();
+ DrawableParams params = new DrawableParams(drawableResourceValue, project,
+ width, height,
+ density, xdpi, ydpi, resources, projectCallback,
+ mMinSdkVersion, mTargetSdkVersion, silentLogger);
+ params.setForceNoDecor();
+ Result result = layoutLibrary.renderDrawable(params);
+ if (result != null && result.isSuccess()) {
+ Object data = result.getData();
+ if (data instanceof BufferedImage) {
+ return (BufferedImage) data;
+ }
+ }
+
+ return null;
+ }
+
ResourceResolver createResolver() {
String theme = mConfigComposite.getTheme();
boolean isProjectTheme = mConfigComposite.isProjectTheme();
import com.android.ide.common.api.Rect;
+import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import java.awt.AlphaComposite;
return false;
}
+ /**
+ * Returns the perceived brightness of the given RGB integer on a scale from 0 to 255
+ *
+ * @param rgb the RGB triplet, 8 bits each
+ * @return the perceived brightness, with 0 maximally dark and 255 maximally bright
+ */
+ public static int getBrightness(int rgb) {
+ if ((rgb & 0xFFFFFF) != 0) {
+ int r = (rgb & 0xFF0000) >> 16;
+ int g = (rgb & 0x00FF00) >> 8;
+ int b = (rgb & 0x0000FF);
+ // See the containsDarkPixels implementation for details
+ return (int) ((299L*r + 587*g + 114*b) / 1000);
+ }
+
+ return 0;
+ }
+
+ /**
+ * Converts an alpha-red-green-blue integer color into an {@link RGB} color.
+ * <p>
+ * <b>NOTE</b> - this will drop the alpha value since {@link RGB} objects do not
+ * contain transparency information.
+ *
+ * @param rgb the RGB integer to convert to a color description
+ * @return the color description corresponding to the integer
+ */
+ public static RGB intToRgb(int rgb) {
+ return new RGB((rgb & 0xFF0000) >>> 16, (rgb & 0xFF00) >>> 8, rgb & 0xFF);
+ }
+
+ /**
+ * Converts an {@link RGB} color into a alpha-red-green-blue integer
+ *
+ * @param rgb the RGB color descriptor to convert
+ * @param alpha the amount of alpha to add into the color integer (since the
+ * {@link RGB} objects do not contain an alpha channel)
+ * @return an integer corresponding to the {@link RGB} color
+ */
+ public static int rgbToInt(RGB rgb, int alpha) {
+ return alpha << 24 | (rgb.red << 16) | (rgb.green << 8) | rgb.blue;
+ }
/**
* Crops blank pixels from the edges of the image and returns the cropped result. We
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
private static final String VALUE_NO_AUTOCLOSE = "noauto"; //$NON-NLS-1$
private final PreviewIconFactory mPreviewIconFactory = new PreviewIconFactory(this);
- private PaletteMode mPaletteMode = PaletteMode.SMALL_PREVIEW;
+ private PaletteMode mPaletteMode = null;
/** Use alphabetical sorting instead of natural order? */
private boolean mAlphabetical;
/** Use categories instead of a single large list of views? */
private String mCurrentTheme;
private String mCurrentDevice;
private IAndroidTarget mCurrentTarget;
+ private AndroidTargetData mCurrentTargetData;
/**
* Create the composite.
super(parent, SWT.NONE);
mEditor = editor;
- loadPaletteMode();
}
/** Reads UI mode from persistent store to preserve palette mode across IDE sessions */
mAlphabetical = paletteModes.contains(VALUE_ALPHABETICAL);
mCategories = !paletteModes.contains(VALUE_NO_CATEGORIES);
mAutoClose = !paletteModes.contains(VALUE_NO_AUTOCLOSE);
+ } else {
+ mPaletteMode = PaletteMode.SMALL_PREVIEW;
}
}
private void refreshPalette() {
IAndroidTarget oldTarget = mCurrentTarget;
mCurrentTarget = null;
+ mCurrentTargetData = null;
mCurrentTheme = null;
mCurrentDevice = null;
reloadPalette(oldTarget);
ConfigurationComposite configuration = mEditor.getConfigurationComposite();
String theme = configuration.getTheme();
String device = configuration.getDevice();
- if (target == mCurrentTarget && mCurrentTheme != null && mCurrentTheme.equals(theme) &&
- mCurrentDevice != null && mCurrentDevice.equals(device)) {
+ AndroidTargetData targetData =
+ target != null ? Sdk.getCurrent().getTargetData(target) : null;
+ if (target == mCurrentTarget && targetData == mCurrentTargetData
+ && mCurrentTheme != null && mCurrentTheme.equals(theme)
+ && mCurrentDevice != null && mCurrentDevice.equals(device)) {
return;
}
mCurrentTheme = theme;
mCurrentTarget = target;
+ mCurrentTargetData = targetData;
mCurrentDevice = device;
mPreviewIconFactory.reset();
+ if (targetData == null) {
+ return;
+ }
+
+ Set<String> expandedCategories = null;
+ if (mAccordion != null) {
+ expandedCategories = mAccordion.getExpandedCategories();
+ // We auto-expand all categories when showing icons-only. When returning to some
+ // other mode we don't want to retain all categories open.
+ if (expandedCategories.size() > 3) {
+ expandedCategories = null;
+ }
+ }
+
// Erase old content and recreate new
for (Control c : getChildren()) {
c.dispose();
}
+ if (mPaletteMode == null) {
+ loadPaletteMode();
+ assert mPaletteMode != null;
+ }
+
if (mPaletteMode.isPreview()) {
if (mForeground != null) {
mForeground.dispose();
mBackground = null;
}
RGB background = mPreviewIconFactory.getBackgroundColor();
- mBackground = new Color(getDisplay(), background);
+ if (background != null) {
+ mBackground = new Color(getDisplay(), background);
+ }
RGB foreground = mPreviewIconFactory.getForegroundColor();
if (foreground != null) {
mForeground = new Color(getDisplay(), foreground);
}
}
- AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target);
-
- List<Object> headers = Collections.emptyList();
+ List<String> headers = Collections.emptyList();
final Map<String, List<ViewElementDescriptor>> categoryToItems;
- if (targetData != null) {
- categoryToItems = new HashMap<String, List<ViewElementDescriptor>>();
- headers = new ArrayList<Object>();
- List<Pair<String,List<ViewElementDescriptor>>> paletteEntries =
- ViewMetadataRepository.get().getPaletteEntries(targetData,
- mAlphabetical, mCategories);
- for (Pair<String,List<ViewElementDescriptor>> pair : paletteEntries) {
- String category = pair.getFirst();
- List<ViewElementDescriptor> categoryItems = pair.getSecond();
- headers.add(category);
- categoryToItems.put(category, categoryItems);
- }
- } else {
- categoryToItems = null;
+ categoryToItems = new HashMap<String, List<ViewElementDescriptor>>();
+ headers = new ArrayList<String>();
+ List<Pair<String,List<ViewElementDescriptor>>> paletteEntries =
+ ViewMetadataRepository.get().getPaletteEntries(targetData,
+ mAlphabetical, mCategories);
+ for (Pair<String,List<ViewElementDescriptor>> pair : paletteEntries) {
+ String category = pair.getFirst();
+ List<ViewElementDescriptor> categoryItems = pair.getSecond();
+ headers.add(category);
+ categoryToItems.put(category, categoryItems);
+ }
+
+ if (expandedCategories == null && headers.size() > 0) {
+ // Expand the first category if we don't have a previous selection (e.g. refresh)
+ expandedCategories = Collections.singleton(headers.get(0));
}
boolean wrap = mPaletteMode.getWrap();
// Pack icon-only view vertically; others stretch to fill palette region
boolean fillVertical = mPaletteMode != PaletteMode.ICON_ONLY;
- mAccordion = new AccordionControl(this, SWT.NONE, headers, fillVertical, wrap) {
+ mAccordion = new AccordionControl(this, SWT.NONE, headers, fillVertical, wrap,
+ expandedCategories) {
@Override
protected Composite createChildContainer(Composite parent) {
Composite composite = super.createChildContainer(parent);
- if (mPaletteMode.isPreview()) {
+ if (mPaletteMode.isPreview() && mBackground != null) {
composite.setBackground(mBackground);
}
addMenu(composite);
imageControl.setScale(scale);
}
imageControl.setHoverColor(getDisplay().getSystemColor(SWT.COLOR_WHITE));
- imageControl.setBackground(mBackground);
+ if (mBackground != null) {
+ imageControl.setBackground(mBackground);
+ }
String toolTip = desc.getUiName();
// It appears pretty much none of the descriptors have tooltips
//String descToolTip = desc.getTooltip();
null, childNode, InsertType.CREATE);
}
+ Integer overrideBgColor = null;
boolean hasTransparency = false;
LayoutLibrary layoutLibrary = editor.getLayoutLibrary();
- if (layoutLibrary != null) {
- hasTransparency = layoutLibrary.supports(Capability.TRANSPARENCY);
+ if (layoutLibrary != null && layoutLibrary.supports(Capability.TRANSPARENCY)) {
+ // It doesn't matter what the background color is as long as the alpha
+ // is 0 (fully transparent). We're using red to make it more obvious if
+ // for some reason the background is painted when it shouldn't be.
+ overrideBgColor = new Integer(0x00FF0000);
}
RenderSession session = null;
int renderHeight = Math.min(screenBounds.height, MAX_RENDER_HEIGHT);
LayoutLog silentLogger = new LayoutLog();
session = editor.render(model, renderWidth, renderHeight,
- null /* explodeNodes */, hasTransparency, silentLogger, RenderingMode.NORMAL);
+ null /* explodeNodes */, overrideBgColor, true /*no decorations*/,
+ silentLogger, RenderingMode.NORMAL);
} catch (Throwable t) {
// Previews can fail for a variety of reasons -- let's not bug
// the user with it
final static int TOGGLE_CATEGORY = 1;
final static int TOGGLE_ALPHABETICAL = 2;
final static int TOGGLE_AUTO_CLOSE = 3;
+ final static int REFRESH = 4;
ToggleViewOptionAction(String title, int action, boolean checked) {
- super(title, IAction.AS_CHECK_BOX);
+ super(title, action == REFRESH ? IAction.AS_PUSH_BUTTON : IAction.AS_CHECK_BOX);
mAction = action;
- setChecked(checked);
+ if (checked) {
+ setChecked(checked);
+ }
}
@Override
mAutoClose = !mAutoClose;
mAccordion.setAutoClose(mAutoClose);
break;
+ case REFRESH:
+ mPreviewIconFactory.refresh();
+ refreshPalette();
+ break;
}
savePaletteMode();
}
for (PaletteMode mode : PaletteMode.values()) {
manager.add(new PaletteModeAction(mode));
}
+ if (mPaletteMode.isPreview()) {
+ manager.add(new Separator());
+ manager.add(new ToggleViewOptionAction("Refresh Previews",
+ ToggleViewOptionAction.REFRESH,
+ false));
+ }
manager.add(new Separator());
manager.add(new ToggleViewOptionAction("Show Categories",
ToggleViewOptionAction.TOGGLE_CATEGORY,
import static com.android.ide.eclipse.adt.AndroidConstants.DOT_PNG;
import static com.android.ide.eclipse.adt.AndroidConstants.DOT_XML;
+import com.android.ide.common.rendering.LayoutLibrary;
+import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceValue;
}
/**
+ * Deletes all the persistent state for the current settings such that it will be regenerated
+ */
+ public void refresh() {
+ File imageDir = getImageDir(false);
+ if (imageDir != null && imageDir.exists()) {
+ File[] files = imageDir.listFiles();
+ for (File file : files) {
+ file.delete();
+ }
+ imageDir.delete();
+ reset();
+ }
+ }
+
+ /**
* Returns an image descriptor for the given element descriptor, or null if no image
* could be computed. The rendering parameters (SDK, theme etc) correspond to those
* stored in the associated palette.
* disk
*/
private boolean render() {
- LayoutEditor layoutEditor = mPalette.getEditor().getLayoutEditor();
+ File imageDir = getImageDir(true);
+
+ GraphicalEditorPart editor = mPalette.getEditor();
+ LayoutEditor layoutEditor = editor.getLayoutEditor();
+ LayoutLibrary layoutLibrary = editor.getLayoutLibrary();
+ Integer overrideBgColor = null;
+ if (layoutLibrary != null) {
+ if (layoutLibrary.supports(Capability.TRANSPARENCY)) {
+ Pair<RGB, RGB> themeColors = getColorsFromTheme();
+ RGB bg = themeColors.getFirst();
+ RGB fg = themeColors.getSecond();
+ storeBackground(imageDir, bg, fg);
+
+ overrideBgColor = Integer.valueOf(ImageUtils.rgbToInt(bg, 0xFF));
+ }
+ }
ViewMetadataRepository repository = ViewMetadataRepository.get();
Document document = repository.getRenderingConfigDoc();
}
UiDocumentNode model = (UiDocumentNode) documentDescriptor.createUiNode();
model.setEditor(layoutEditor);
- GraphicalEditorPart editor = mPalette.getEditor();
model.setUnknownDescriptorProvider(editor.getModel().getUnknownDescriptorProvider());
Element documentElement = document.getDocumentElement();
int height = 2000;
Set<UiElementNode> expandNodes = Collections.<UiElementNode>emptySet();
RenderingMode renderingMode = RenderingMode.FULL_EXPAND;
+
session = editor.render(model, width, height, expandNodes,
- false /*hasTransparency*/, logger,
+ overrideBgColor, true /*no decorations*/, logger,
renderingMode);
} catch (Throwable t) {
if (session.getResult().isSuccess()) {
BufferedImage image = session.getImage();
if (image != null && image.getWidth() > 0 && image.getHeight() > 0) {
- File imageDir = getImageDir(true);
- // TODO - use resource resolution instead?
+ // Fallback for older platforms where we couldn't do background rendering
+ // at the beginning of this method
if (mBackground == null) {
Pair<RGB, RGB> themeColors = getColorsFromTheme();
-
RGB bg = themeColors.getFirst();
RGB fg = themeColors.getSecond();
if (bg == null) {
+ // Just use a pixel from the rendering instead.
int p = image.getRGB(image.getWidth() - 1, image.getHeight() - 1);
- bg = new RGB((p & 0xFF0000) >> 16, (p & 0xFF00) >> 8, p & 0xFF);
- // This isn't reliable - for example, for some themes the
- // background is a 9 patch image - so in this case don't
- // set the foreground color
- fg = null;
+ // However, in this case we don't trust the foreground color
+ // even if one was found in the themes; pick one that is guaranteed
+ // to contrast with the background
+ bg = ImageUtils.intToRgb(p);
+ if (ImageUtils.getBrightness(ImageUtils.rgbToInt(bg, 255)) < 128) {
+ fg = new RGB(255, 255, 255);
+ } else {
+ fg = new RGB(0, 0, 0);
+ }
}
-
storeBackground(imageDir, bg, fg);
+ assert mBackground != null;
}
List<ViewInfo> viewInfoList = session.getRootViews();
if (theme != null) {
background = resolveThemeColor(resources, "windowBackground"); //$NON-NLS-1$
if (background == null) {
- background = resolveThemeColor(resources, "colorBackground"); //$NON-NLS-1$
+ background = renderDrawableResource("windowBackground"); //$NON-NLS-1$
+ // This causes some harm with some themes: We'll find a color, say black,
+ // that isn't actually rendered in the theme. Better to use null here,
+ // which will cause the caller to pick a pixel from the observed background
+ // instead.
+ //if (background == null) {
+ // background = resolveThemeColor(resources, "colorBackground"); //$NON-NLS-1$
+ //}
}
foreground = resolveThemeColor(resources, "textColorPrimary"); //$NON-NLS-1$
}
+ // Ensure that the foreground color is suitably distinct from the background color
+ if (background != null) {
+ int bgRgb = ImageUtils.rgbToInt(background, 0xFF);
+ int backgroundBrightness = ImageUtils.getBrightness(bgRgb);
+ if (foreground == null) {
+ if (backgroundBrightness < 128) {
+ foreground = new RGB(255, 255, 255);
+ } else {
+ foreground = new RGB(0, 0, 0);
+ }
+ } else {
+ int fgRgb = ImageUtils.rgbToInt(foreground, 0xFF);
+ int foregroundBrightness = ImageUtils.getBrightness(fgRgb);
+ if (Math.abs(backgroundBrightness - foregroundBrightness) < 64) {
+ if (backgroundBrightness < 128) {
+ foreground = new RGB(255, 255, 255);
+ } else {
+ foreground = new RGB(0, 0, 0);
+ }
+ }
+ }
+ }
+
return Pair.of(background, foreground);
}
+ /**
+ * Renders the given resource which should refer to a drawable and returns a
+ * representative color value for the drawable (such as the color in the center)
+ *
+ * @param themeItemName the item in the theme to be looked up and rendered
+ * @return a color representing a typical color in the drawable
+ */
+ private RGB renderDrawableResource(String themeItemName) {
+ GraphicalEditorPart editor = mPalette.getEditor();
+ BufferedImage image = editor.renderThemeItem(themeItemName, 100, 100);
+ if (image != null) {
+ // Use the middle pixel as the color since that works better for gradients;
+ // solid colors work too.
+ int rgb = image.getRGB(image.getWidth() / 2, image.getHeight() / 2);
+ return ImageUtils.intToRgb(rgb);
+ }
+
+ return null;
+ }
+
private static RGB resolveThemeColor(ResourceResolver resources, String resourceName) {
ResourceValue textColor = resources.findItemInTheme(resourceName);
textColor = resources.resolveResValue(textColor);
try {
int rgba = ImageUtils.getColor(value);
// Drop alpha channel
- return new RGB((rgba & 0xFF0000) >> 16, (rgba & 0xFF00) >> 8, rgba & 0xFF);
+ return ImageUtils.intToRgb(rgba);
} catch (NumberFormatException nfe) {
;
}
if (themeName.startsWith(themeNamePrefix)) {
themeName = themeName.substring(themeNamePrefix.length());
}
- String dirName = String.format("palette-preview-%s-%s-%s", cleanup(targetName),
+ String dirName = String.format("palette-preview-r10-%s-%s-%s", cleanup(targetName),
cleanup(themeName), cleanup(mPalette.getCurrentDevice()));
IPath dirPath = pluginState.append(dirName);
mForeground = fg;
File file = new File(imageDir, PREVIEW_INFO_FILE);
String colors = String.format(
- "background=#%02x%02x%02x\nforeground=#%02x%02x%02x\\n", //$NON-NLS-1$
+ "background=#%02x%02x%02x\nforeground=#%02x%02x%02x\n", //$NON-NLS-1$
bg.red, bg.green, bg.blue,
fg.red, fg.green, fg.blue);
AdtPlugin.writeFile(file, colors);
String colorString = (String) properties.get("background"); //$NON-NLS-1$
if (colorString != null) {
int rgb = ImageUtils.getColor(colorString.trim());
- mBackground = new RGB((rgb & 0xFF0000) >> 16, (rgb & 0xFF00) >> 8, rgb & 0xFF);
+ mBackground = ImageUtils.intToRgb(rgb);
}
colorString = (String) properties.get("foreground"); //$NON-NLS-1$
if (colorString != null) {
int rgb = ImageUtils.getColor(colorString.trim());
- mForeground = new RGB((rgb & 0xFF0000) >> 16, (rgb & 0xFF00) >> 8, rgb & 0xFF);
+ mForeground = ImageUtils.intToRgb(rgb);
}
}
assertEquals(0xABCDEF91, ImageUtils.getColor("#ABCDEF91"));
}
+ public void testGetBrightness() throws Exception {
+ assertEquals(96, ImageUtils.getBrightness(0x456789));
+ assertEquals(198, ImageUtils.getBrightness(0xABCDEF));
+
+ assertEquals(0, ImageUtils.getBrightness(0x0));
+ assertEquals(255, ImageUtils.getBrightness(0xFFFFFF));
+ assertEquals(299*255/1000, ImageUtils.getBrightness(0xFF0000));
+ assertEquals(587*255/1000, ImageUtils.getBrightness(0x00FF00));
+ assertEquals(114*255/1000, ImageUtils.getBrightness(0x0000FF));
+ }
+
+ public void testColorConversion() throws Exception {
+ assertEquals(0, ImageUtils.rgbToInt(ImageUtils.intToRgb(0), 0));
+ assertEquals(0xFFFFFFFF, ImageUtils.rgbToInt(ImageUtils.intToRgb(0xFFFFFF), 0xFF));
+ assertEquals(0x12345678, ImageUtils.rgbToInt(ImageUtils.intToRgb(0x345678), 0x12));
+ }
+
public void testScaleImage() throws Exception {
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics g = image.getGraphics();