aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java
deleted file mode 100644
index 5621d5f17..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java
+++ /dev/null
@@ -1,1333 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.android.ide.eclipse.adt.internal.editors.layout.gle2;
-
-import static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX;
-import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
-import static com.android.SdkConstants.STYLE_RESOURCE_PREFIX;
-import static com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration.MASK_RENDERING;
-import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
-import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SMALL_SHADOW_SIZE;
-import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.DEFAULT;
-import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.INCLUDES;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.ide.common.resources.ResourceFile;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.ResourceResolver;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationClient;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationDescription;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Locale;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.NestedConfiguration;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.VaryingConfiguration;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder.Reference;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.io.IFileWrapper;
-import com.android.io.IAbstractFile;
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-import com.android.resources.ScreenOrientation;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.devices.Device;
-import com.android.sdklib.devices.Screen;
-import com.android.sdklib.devices.State;
-import com.android.utils.SdkUtils;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.IJobChangeEvent;
-import org.eclipse.core.runtime.jobs.IJobChangeListener;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.dialogs.InputDialog;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Region;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.progress.UIJob;
-import org.w3c.dom.Document;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.lang.ref.SoftReference;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Represents a preview rendering of a given configuration
- */
-public class RenderPreview implements IJobChangeListener {
- /** Whether previews should use large shadows */
- static final boolean LARGE_SHADOWS = false;
-
- /**
- * Still doesn't work; get exceptions from layoutlib:
- * java.lang.IllegalStateException: After scene creation, #init() must be called
- * at com.android.layoutlib.bridge.impl.RenderAction.acquire(RenderAction.java:151)
- * <p>
- * TODO: Investigate.
- */
- private static final boolean RENDER_ASYNC = false;
-
- /**
- * Height of the toolbar shown over a preview during hover. Needs to be
- * large enough to accommodate icons below.
- */
- private static final int HEADER_HEIGHT = 20;
-
- /** Whether to dump out rendering failures of the previews to the log */
- private static final boolean DUMP_RENDER_DIAGNOSTICS = false;
-
- /** Extra error checking in debug mode */
- private static final boolean DEBUG = false;
-
- private static final Image EDIT_ICON;
- private static final Image ZOOM_IN_ICON;
- private static final Image ZOOM_OUT_ICON;
- private static final Image CLOSE_ICON;
- private static final int EDIT_ICON_WIDTH;
- private static final int ZOOM_IN_ICON_WIDTH;
- private static final int ZOOM_OUT_ICON_WIDTH;
- private static final int CLOSE_ICON_WIDTH;
- static {
- ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
- IconFactory icons = IconFactory.getInstance();
- CLOSE_ICON = sharedImages.getImage(ISharedImages.IMG_ETOOL_DELETE);
- EDIT_ICON = icons.getIcon("editPreview"); //$NON-NLS-1$
- ZOOM_IN_ICON = icons.getIcon("zoomplus"); //$NON-NLS-1$
- ZOOM_OUT_ICON = icons.getIcon("zoomminus"); //$NON-NLS-1$
- CLOSE_ICON_WIDTH = CLOSE_ICON.getImageData().width;
- EDIT_ICON_WIDTH = EDIT_ICON.getImageData().width;
- ZOOM_IN_ICON_WIDTH = ZOOM_IN_ICON.getImageData().width;
- ZOOM_OUT_ICON_WIDTH = ZOOM_OUT_ICON.getImageData().width;
- }
-
- /** The configuration being previewed */
- private @NonNull Configuration mConfiguration;
-
- /** Configuration to use if we have an alternate input to be rendered */
- private @NonNull Configuration mAlternateConfiguration;
-
- /** The associated manager */
- private final @NonNull RenderPreviewManager mManager;
- private final @NonNull LayoutCanvas mCanvas;
-
- private @NonNull SoftReference<ResourceResolver> mResourceResolver =
- new SoftReference<ResourceResolver>(null);
- private @Nullable Job mJob;
- private @Nullable Image mThumbnail;
- private @Nullable String mDisplayName;
- private int mWidth;
- private int mHeight;
- private int mX;
- private int mY;
- private int mTitleHeight;
- private double mScale = 1.0;
- private double mAspectRatio;
-
- /** If non null, points to a separate file containing the source */
- private @Nullable IFile mAlternateInput;
-
- /** If included within another layout, the name of that outer layout */
- private @Nullable Reference mIncludedWithin;
-
- /** Whether the mouse is actively hovering over this preview */
- private boolean mActive;
-
- /**
- * Whether this preview cannot be rendered because of a model error - such
- * as an invalid configuration, a missing resource, an error in the XML
- * markup, etc. If non null, contains the error message (or a blank string
- * if not known), and null if the render was successful.
- */
- private String mError;
-
- /** Whether in the current layout, this preview is visible */
- private boolean mVisible;
-
- /** Whether the configuration has changed and needs to be refreshed the next time
- * this preview made visible. This corresponds to the change flags in
- * {@link ConfigurationClient}. */
- private int mDirty;
-
- /**
- * Creates a new {@linkplain RenderPreview}
- *
- * @param manager the manager
- * @param canvas canvas where preview is painted
- * @param configuration the associated configuration
- * @param width the initial width to use for the preview
- * @param height the initial height to use for the preview
- */
- private RenderPreview(
- @NonNull RenderPreviewManager manager,
- @NonNull LayoutCanvas canvas,
- @NonNull Configuration configuration) {
- mManager = manager;
- mCanvas = canvas;
- mConfiguration = configuration;
- updateSize();
-
- // Should only attempt to create configurations for fully configured devices
- assert mConfiguration.getDevice() != null
- && mConfiguration.getDeviceState() != null
- && mConfiguration.getLocale() != null
- && mConfiguration.getTarget() != null
- && mConfiguration.getTheme() != null
- && mConfiguration.getFullConfig() != null
- && mConfiguration.getFullConfig().getScreenSizeQualifier() != null :
- mConfiguration;
- }
-
- /**
- * Sets the configuration to use for this preview
- *
- * @param configuration the new configuration
- */
- public void setConfiguration(@NonNull Configuration configuration) {
- mConfiguration = configuration;
- }
-
- /**
- * Gets the scale being applied to the thumbnail
- *
- * @return the scale being applied to the thumbnail
- */
- public double getScale() {
- return mScale;
- }
-
- /**
- * Sets the scale to apply to the thumbnail
- *
- * @param scale the factor to scale the thumbnail picture by
- */
- public void setScale(double scale) {
- disposeThumbnail();
- mScale = scale;
- }
-
- /**
- * Returns the aspect ratio of this render preview
- *
- * @return the aspect ratio
- */
- public double getAspectRatio() {
- return mAspectRatio;
- }
-
- /**
- * Returns whether the preview is actively hovered
- *
- * @return whether the mouse is hovering over the preview
- */
- public boolean isActive() {
- return mActive;
- }
-
- /**
- * Sets whether the preview is actively hovered
- *
- * @param active if the mouse is hovering over the preview
- */
- public void setActive(boolean active) {
- mActive = active;
- }
-
- /**
- * Returns whether the preview is visible. Previews that are off
- * screen are typically marked invisible during layout, which means we don't
- * have to expend effort computing preview thumbnails etc
- *
- * @return true if the preview is visible
- */
- public boolean isVisible() {
- return mVisible;
- }
-
- /**
- * Returns whether this preview represents a forked layout
- *
- * @return true if this preview represents a separate file
- */
- public boolean isForked() {
- return mAlternateInput != null || mIncludedWithin != null;
- }
-
- /**
- * Returns the file to be used for this preview, or null if this is not a
- * forked layout meaning that the file is the one used in the chooser
- *
- * @return the file or null for non-forked layouts
- */
- @Nullable
- public IFile getAlternateInput() {
- if (mAlternateInput != null) {
- return mAlternateInput;
- } else if (mIncludedWithin != null) {
- return mIncludedWithin.getFile();
- }
-
- return null;
- }
-
- /**
- * Returns the area of this render preview, PRIOR to scaling
- *
- * @return the area (width times height without scaling)
- */
- int getArea() {
- return mWidth * mHeight;
- }
-
- /**
- * Sets whether the preview is visible. Previews that are off
- * screen are typically marked invisible during layout, which means we don't
- * have to expend effort computing preview thumbnails etc
- *
- * @param visible whether this preview is visible
- */
- public void setVisible(boolean visible) {
- if (visible != mVisible) {
- mVisible = visible;
- if (mVisible) {
- if (mDirty != 0) {
- // Just made the render preview visible:
- configurationChanged(mDirty); // schedules render
- } else {
- updateForkStatus();
- mManager.scheduleRender(this);
- }
- } else {
- dispose();
- }
- }
- }
-
- /**
- * Sets the layout position relative to the top left corner of the preview
- * area, in control coordinates
- */
- void setPosition(int x, int y) {
- mX = x;
- mY = y;
- }
-
- /**
- * Gets the layout X position relative to the top left corner of the preview
- * area, in control coordinates
- */
- int getX() {
- return mX;
- }
-
- /**
- * Gets the layout Y position relative to the top left corner of the preview
- * area, in control coordinates
- */
- int getY() {
- return mY;
- }
-
- /** Determine whether this configuration has a better match in a different layout file */
- private void updateForkStatus() {
- ConfigurationChooser chooser = mManager.getChooser();
- FolderConfiguration config = mConfiguration.getFullConfig();
- if (mAlternateInput != null && chooser.isBestMatchFor(mAlternateInput, config)) {
- return;
- }
-
- mAlternateInput = null;
- IFile editedFile = chooser.getEditedFile();
- if (editedFile != null) {
- if (!chooser.isBestMatchFor(editedFile, config)) {
- ProjectResources resources = chooser.getResources();
- if (resources != null) {
- ResourceFile best = resources.getMatchingFile(editedFile.getName(),
- ResourceType.LAYOUT, config);
- if (best != null) {
- IAbstractFile file = best.getFile();
- if (file instanceof IFileWrapper) {
- mAlternateInput = ((IFileWrapper) file).getIFile();
- } else if (file instanceof File) {
- mAlternateInput = AdtUtils.fileToIFile(((File) file));
- }
- }
- }
- if (mAlternateInput != null) {
- mAlternateConfiguration = Configuration.create(mConfiguration,
- mAlternateInput);
- }
- }
- }
- }
-
- /**
- * Creates a new {@linkplain RenderPreview}
- *
- * @param manager the manager
- * @param configuration the associated configuration
- * @return a new configuration
- */
- @NonNull
- public static RenderPreview create(
- @NonNull RenderPreviewManager manager,
- @NonNull Configuration configuration) {
- LayoutCanvas canvas = manager.getCanvas();
- return new RenderPreview(manager, canvas, configuration);
- }
-
- /**
- * Throws away this preview: cancels any pending rendering jobs and disposes
- * of image resources etc
- */
- public void dispose() {
- disposeThumbnail();
-
- if (mJob != null) {
- mJob.cancel();
- mJob = null;
- }
- }
-
- /** Disposes the thumbnail rendering. */
- void disposeThumbnail() {
- if (mThumbnail != null) {
- mThumbnail.dispose();
- mThumbnail = null;
- }
- }
-
- /**
- * Returns the display name of this preview
- *
- * @return the name of the preview
- */
- @NonNull
- public String getDisplayName() {
- if (mDisplayName == null) {
- String displayName = getConfiguration().getDisplayName();
- if (displayName == null) {
- // No display name: this must be the configuration used by default
- // for the view which is originally displayed (before adding thumbnails),
- // and you've switched away to something else; now we need to display a name
- // for this original configuration. For now, just call it "Original"
- return "Original";
- }
-
- return displayName;
- }
-
- return mDisplayName;
- }
-
- /**
- * Sets the display name of this preview. By default, the display name is
- * the display name of the configuration, but it can be overridden by calling
- * this setter (which only sets the preview name, without editing the configuration.)
- *
- * @param displayName the new display name
- */
- public void setDisplayName(@NonNull String displayName) {
- mDisplayName = displayName;
- }
-
- /**
- * Sets an inclusion context to use for this layout, if any. This will render
- * the configuration preview as the outer layout with the current layout
- * embedded within.
- *
- * @param includedWithin a reference to a layout which includes this one
- */
- public void setIncludedWithin(Reference includedWithin) {
- mIncludedWithin = includedWithin;
- }
-
- /**
- * Request a new render after the given delay
- *
- * @param delay the delay to wait before starting the render job
- */
- public void render(long delay) {
- Job job = mJob;
- if (job != null) {
- job.cancel();
- }
- if (RENDER_ASYNC) {
- job = new AsyncRenderJob();
- } else {
- job = new RenderJob();
- }
- job.schedule(delay);
- job.addJobChangeListener(this);
- mJob = job;
- }
-
- /** Render immediately */
- private void renderSync() {
- GraphicalEditorPart editor = mCanvas.getEditorDelegate().getGraphicalEditor();
- if (editor.getReadyLayoutLib(false /*displayError*/) == null) {
- // Don't attempt to render when there is no ready layout library: most likely
- // the targets are loading/reloading.
- return;
- }
-
- disposeThumbnail();
-
- Configuration configuration =
- mAlternateInput != null && mAlternateConfiguration != null
- ? mAlternateConfiguration : mConfiguration;
- ResourceResolver resolver = getResourceResolver(configuration);
- RenderService renderService = RenderService.create(editor, configuration, resolver);
-
- if (mIncludedWithin != null) {
- renderService.setIncludedWithin(mIncludedWithin);
- }
-
- if (mAlternateInput != null) {
- IAndroidTarget target = editor.getRenderingTarget();
- AndroidTargetData data = null;
- if (target != null) {
- Sdk sdk = Sdk.getCurrent();
- if (sdk != null) {
- data = sdk.getTargetData(target);
- }
- }
-
- // Construct UI model from XML
- DocumentDescriptor documentDescriptor;
- if (data == null) {
- documentDescriptor = new DocumentDescriptor("temp", null);//$NON-NLS-1$
- } else {
- documentDescriptor = data.getLayoutDescriptors().getDescriptor();
- }
- UiDocumentNode model = (UiDocumentNode) documentDescriptor.createUiNode();
- model.setEditor(mCanvas.getEditorDelegate().getEditor());
- model.setUnknownDescriptorProvider(editor.getModel().getUnknownDescriptorProvider());
-
- Document document = DomUtilities.getDocument(mAlternateInput);
- if (document == null) {
- mError = "No document";
- createErrorThumbnail();
- return;
- }
- model.loadFromXmlNode(document);
- renderService.setModel(model);
- } else {
- renderService.setModel(editor.getModel());
- }
- RenderLogger log = editor.createRenderLogger(getDisplayName());
- renderService.setLog(log);
- RenderSession session = renderService.createRenderSession();
- Result render = session.render(1000);
-
- if (DUMP_RENDER_DIAGNOSTICS) {
- if (log.hasProblems() || !render.isSuccess()) {
- AdtPlugin.log(IStatus.ERROR, "Found problems rendering preview "
- + getDisplayName() + ": "
- + render.getErrorMessage() + " : "
- + log.getProblems(false));
- Throwable exception = render.getException();
- if (exception != null) {
- AdtPlugin.log(exception, "Failure rendering preview " + getDisplayName());
- }
- }
- }
-
- if (render.isSuccess()) {
- mError = null;
- } else {
- mError = render.getErrorMessage();
- if (mError == null) {
- mError = "";
- }
- }
-
- if (render.getStatus() == Status.ERROR_TIMEOUT) {
- // TODO: Special handling? schedule update again later
- return;
- }
- if (render.isSuccess()) {
- BufferedImage image = session.getImage();
- if (image != null) {
- createThumbnail(image);
- }
- }
-
- if (mError != null) {
- createErrorThumbnail();
- }
- }
-
- private ResourceResolver getResourceResolver(Configuration configuration) {
- ResourceResolver resourceResolver = mResourceResolver.get();
- if (resourceResolver != null) {
- return resourceResolver;
- }
-
- GraphicalEditorPart graphicalEditor = mCanvas.getEditorDelegate().getGraphicalEditor();
- String theme = configuration.getTheme();
- if (theme == null) {
- return null;
- }
-
- Map<ResourceType, Map<String, ResourceValue>> configuredFrameworkRes = null;
- Map<ResourceType, Map<String, ResourceValue>> configuredProjectRes = null;
-
- FolderConfiguration config = configuration.getFullConfig();
- IAndroidTarget target = graphicalEditor.getRenderingTarget();
- ResourceRepository frameworkRes = null;
- if (target != null) {
- Sdk sdk = Sdk.getCurrent();
- if (sdk == null) {
- return null;
- }
- AndroidTargetData data = sdk.getTargetData(target);
-
- if (data != null) {
- // TODO: SHARE if possible
- frameworkRes = data.getFrameworkResources();
- configuredFrameworkRes = frameworkRes.getConfiguredResources(config);
- } else {
- return null;
- }
- } else {
- return null;
- }
- assert configuredFrameworkRes != null;
-
-
- // get the resources of the file's project.
- ProjectResources projectRes = ResourceManager.getInstance().getProjectResources(
- graphicalEditor.getProject());
- configuredProjectRes = projectRes.getConfiguredResources(config);
-
- if (!theme.startsWith(PREFIX_RESOURCE_REF)) {
- if (frameworkRes.hasResourceItem(ANDROID_STYLE_RESOURCE_PREFIX + theme)) {
- theme = ANDROID_STYLE_RESOURCE_PREFIX + theme;
- } else {
- theme = STYLE_RESOURCE_PREFIX + theme;
- }
- }
-
- resourceResolver = ResourceResolver.create(
- configuredProjectRes, configuredFrameworkRes,
- ResourceHelper.styleToTheme(theme),
- ResourceHelper.isProjectStyle(theme));
- mResourceResolver = new SoftReference<ResourceResolver>(resourceResolver);
- return resourceResolver;
- }
-
- /**
- * Sets the new image of the preview and generates a thumbnail
- *
- * @param image the full size image
- */
- void createThumbnail(BufferedImage image) {
- if (image == null) {
- mThumbnail = null;
- return;
- }
-
- ImageOverlay imageOverlay = mCanvas.getImageOverlay();
- boolean drawShadows = imageOverlay == null || imageOverlay.getShowDropShadow();
- double scale = getWidth() / (double) image.getWidth();
- int shadowSize;
- if (LARGE_SHADOWS) {
- shadowSize = drawShadows ? SHADOW_SIZE : 0;
- } else {
- shadowSize = drawShadows ? SMALL_SHADOW_SIZE : 0;
- }
- if (scale < 1.0) {
- if (LARGE_SHADOWS) {
- image = ImageUtils.scale(image, scale, scale,
- shadowSize, shadowSize);
- if (drawShadows) {
- ImageUtils.drawRectangleShadow(image, 0, 0,
- image.getWidth() - shadowSize,
- image.getHeight() - shadowSize);
- }
- } else {
- image = ImageUtils.scale(image, scale, scale,
- shadowSize, shadowSize);
- if (drawShadows) {
- ImageUtils.drawSmallRectangleShadow(image, 0, 0,
- image.getWidth() - shadowSize,
- image.getHeight() - shadowSize);
- }
- }
- }
-
- mThumbnail = SwtUtils.convertToSwt(mCanvas.getDisplay(), image,
- true /* transferAlpha */, -1);
- }
-
- void createErrorThumbnail() {
- int shadowSize = LARGE_SHADOWS ? SHADOW_SIZE : SMALL_SHADOW_SIZE;
- int width = getWidth();
- int height = getHeight();
- BufferedImage image = new BufferedImage(width + shadowSize, height + shadowSize,
- BufferedImage.TYPE_INT_ARGB);
-
- Graphics2D g = image.createGraphics();
- g.setColor(new java.awt.Color(0xfffbfcc6));
- g.fillRect(0, 0, width, height);
-
- g.dispose();
-
- ImageOverlay imageOverlay = mCanvas.getImageOverlay();
- boolean drawShadows = imageOverlay == null || imageOverlay.getShowDropShadow();
- if (drawShadows) {
- if (LARGE_SHADOWS) {
- ImageUtils.drawRectangleShadow(image, 0, 0,
- image.getWidth() - SHADOW_SIZE,
- image.getHeight() - SHADOW_SIZE);
- } else {
- ImageUtils.drawSmallRectangleShadow(image, 0, 0,
- image.getWidth() - SMALL_SHADOW_SIZE,
- image.getHeight() - SMALL_SHADOW_SIZE);
- }
- }
-
- mThumbnail = SwtUtils.convertToSwt(mCanvas.getDisplay(), image,
- true /* transferAlpha */, -1);
- }
-
- private static double getScale(int width, int height) {
- int maxWidth = RenderPreviewManager.getMaxWidth();
- int maxHeight = RenderPreviewManager.getMaxHeight();
- if (width > 0 && height > 0
- && (width > maxWidth || height > maxHeight)) {
- if (width >= height) { // landscape
- return maxWidth / (double) width;
- } else { // portrait
- return maxHeight / (double) height;
- }
- }
-
- return 1.0;
- }
-
- /**
- * Returns the width of the preview, in pixels
- *
- * @return the width in pixels
- */
- public int getWidth() {
- return (int) (mWidth * mScale * RenderPreviewManager.getScale());
- }
-
- /**
- * Returns the height of the preview, in pixels
- *
- * @return the height in pixels
- */
- public int getHeight() {
- return (int) (mHeight * mScale * RenderPreviewManager.getScale());
- }
-
- /**
- * Handles clicks within the preview (x and y are positions relative within the
- * preview
- *
- * @param x the x coordinate within the preview where the click occurred
- * @param y the y coordinate within the preview where the click occurred
- * @return true if this preview handled (and therefore consumed) the click
- */
- public boolean click(int x, int y) {
- if (y >= mTitleHeight && y < mTitleHeight + HEADER_HEIGHT) {
- int left = 0;
- left += CLOSE_ICON_WIDTH;
- if (x <= left) {
- // Delete
- mManager.deletePreview(this);
- return true;
- }
- left += ZOOM_IN_ICON_WIDTH;
- if (x <= left) {
- // Zoom in
- mScale = mScale * (1 / 0.5);
- if (Math.abs(mScale-1.0) < 0.0001) {
- mScale = 1.0;
- }
-
- render(0);
- mManager.layout(true);
- mCanvas.redraw();
- return true;
- }
- left += ZOOM_OUT_ICON_WIDTH;
- if (x <= left) {
- // Zoom out
- mScale = mScale * (0.5 / 1);
- if (Math.abs(mScale-1.0) < 0.0001) {
- mScale = 1.0;
- }
- render(0);
-
- mManager.layout(true);
- mCanvas.redraw();
- return true;
- }
- left += EDIT_ICON_WIDTH;
- if (x <= left) {
- // Edit. For now, just rename
- InputDialog d = new InputDialog(
- AdtPlugin.getShell(),
- "Rename Preview", // title
- "Name:",
- getDisplayName(),
- null);
- if (d.open() == Window.OK) {
- String newName = d.getValue();
- mConfiguration.setDisplayName(newName);
- if (mDescription != null) {
- mManager.rename(mDescription, newName);
- }
- mCanvas.redraw();
- }
-
- return true;
- }
-
- // Clicked anywhere else on header
- // Perhaps open Edit dialog here?
- }
-
- mManager.switchTo(this);
- return true;
- }
-
- /**
- * Paints the preview at the given x/y position
- *
- * @param gc the graphics context to paint it into
- * @param x the x coordinate to paint the preview at
- * @param y the y coordinate to paint the preview at
- */
- void paint(GC gc, int x, int y) {
- mTitleHeight = paintTitle(gc, x, y, true /*showFile*/);
- y += mTitleHeight;
- y += 2;
-
- int width = getWidth();
- int height = getHeight();
- if (mThumbnail != null && mError == null) {
- gc.drawImage(mThumbnail, x, y);
-
- if (mActive) {
- int oldWidth = gc.getLineWidth();
- gc.setLineWidth(3);
- gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION));
- gc.drawRectangle(x - 1, y - 1, width + 2, height + 2);
- gc.setLineWidth(oldWidth);
- }
- } else if (mError != null) {
- if (mThumbnail != null) {
- gc.drawImage(mThumbnail, x, y);
- } else {
- gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WIDGET_BORDER));
- gc.drawRectangle(x, y, width, height);
- }
-
- gc.setClipping(x, y, width, height);
- Image icon = IconFactory.getInstance().getIcon("renderError"); //$NON-NLS-1$
- ImageData data = icon.getImageData();
- int prevAlpha = gc.getAlpha();
- int alpha = 96;
- if (mThumbnail != null) {
- alpha -= 32;
- }
- gc.setAlpha(alpha);
- gc.drawImage(icon, x + (width - data.width) / 2, y + (height - data.height) / 2);
-
- String msg = mError;
- Density density = mConfiguration.getDensity();
- if (density == Density.TV || density == Density.LOW) {
- msg = "Broken rendering library; unsupported DPI. Try using the SDK manager " +
- "to get updated layout libraries.";
- }
- int charWidth = gc.getFontMetrics().getAverageCharWidth();
- int charsPerLine = (width - 10) / charWidth;
- msg = SdkUtils.wrap(msg, charsPerLine, null);
- gc.setAlpha(255);
- gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
- gc.drawText(msg, x + 5, y + HEADER_HEIGHT, true);
- gc.setAlpha(prevAlpha);
- gc.setClipping((Region) null);
- } else {
- gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WIDGET_BORDER));
- gc.drawRectangle(x, y, width, height);
-
- Image icon = IconFactory.getInstance().getIcon("refreshPreview"); //$NON-NLS-1$
- ImageData data = icon.getImageData();
- int prevAlpha = gc.getAlpha();
- gc.setAlpha(96);
- gc.drawImage(icon, x + (width - data.width) / 2,
- y + (height - data.height) / 2);
- gc.setAlpha(prevAlpha);
- }
-
- if (mActive) {
- int left = x ;
- int prevAlpha = gc.getAlpha();
- gc.setAlpha(208);
- Color bg = mCanvas.getDisplay().getSystemColor(SWT.COLOR_WHITE);
- gc.setBackground(bg);
- gc.fillRectangle(left, y, x + width - left, HEADER_HEIGHT);
- gc.setAlpha(prevAlpha);
-
- y += 2;
-
- // Paint icons
- gc.drawImage(CLOSE_ICON, left, y);
- left += CLOSE_ICON_WIDTH;
-
- gc.drawImage(ZOOM_IN_ICON, left, y);
- left += ZOOM_IN_ICON_WIDTH;
-
- gc.drawImage(ZOOM_OUT_ICON, left, y);
- left += ZOOM_OUT_ICON_WIDTH;
-
- gc.drawImage(EDIT_ICON, left, y);
- left += EDIT_ICON_WIDTH;
- }
- }
-
- /**
- * Paints the preview title at the given position (and returns the required
- * height)
- *
- * @param gc the graphics context to paint into
- * @param x the left edge of the preview rectangle
- * @param y the top edge of the preview rectangle
- */
- private int paintTitle(GC gc, int x, int y, boolean showFile) {
- String displayName = getDisplayName();
- return paintTitle(gc, x, y, showFile, displayName);
- }
-
- /**
- * Paints the preview title at the given position (and returns the required
- * height)
- *
- * @param gc the graphics context to paint into
- * @param x the left edge of the preview rectangle
- * @param y the top edge of the preview rectangle
- * @param displayName the title string to be used
- */
- int paintTitle(GC gc, int x, int y, boolean showFile, String displayName) {
- int titleHeight = 0;
-
- if (showFile && mIncludedWithin != null) {
- if (mManager.getMode() != INCLUDES) {
- displayName = "<include>";
- } else {
- // Skip: just paint footer instead
- displayName = null;
- }
- }
-
- int width = getWidth();
- int labelTop = y + 1;
- gc.setClipping(x, labelTop, width, 100);
-
- // Use font height rather than extent height since we want two adjacent
- // previews (which may have different display names and therefore end
- // up with slightly different extent heights) to have identical title
- // heights such that they are aligned identically
- int fontHeight = gc.getFontMetrics().getHeight();
-
- if (displayName != null && displayName.length() > 0) {
- gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
- Point extent = gc.textExtent(displayName);
- int labelLeft = Math.max(x, x + (width - extent.x) / 2);
- Image icon = null;
- Locale locale = mConfiguration.getLocale();
- if (locale != null && (locale.hasLanguage() || locale.hasRegion())
- && (!(mConfiguration instanceof NestedConfiguration)
- || ((NestedConfiguration) mConfiguration).isOverridingLocale())) {
- icon = locale.getFlagImage();
- }
-
- if (icon != null) {
- int flagWidth = icon.getImageData().width;
- int flagHeight = icon.getImageData().height;
- labelLeft = Math.max(x + flagWidth / 2, labelLeft);
- gc.drawImage(icon, labelLeft - flagWidth / 2 - 1, labelTop);
- labelLeft += flagWidth / 2 + 1;
- gc.drawText(displayName, labelLeft,
- labelTop - (extent.y - flagHeight) / 2, true);
- } else {
- gc.drawText(displayName, labelLeft, labelTop, true);
- }
-
- labelTop += extent.y;
- titleHeight += fontHeight;
- }
-
- if (showFile && (mAlternateInput != null || mIncludedWithin != null)) {
- // Draw file flag, and parent folder name
- IFile file = mAlternateInput != null
- ? mAlternateInput : mIncludedWithin.getFile();
- String fileName = file.getParent().getName() + File.separator
- + file.getName();
- Point extent = gc.textExtent(fileName);
- Image icon = IconFactory.getInstance().getIcon("android_file"); //$NON-NLS-1$
- int flagWidth = icon.getImageData().width;
- int flagHeight = icon.getImageData().height;
-
- int labelLeft = Math.max(x, x + (width - extent.x - flagWidth - 1) / 2);
-
- gc.drawImage(icon, labelLeft, labelTop);
-
- gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
- labelLeft += flagWidth + 1;
- labelTop -= (extent.y - flagHeight) / 2;
- gc.drawText(fileName, labelLeft, labelTop, true);
-
- titleHeight += Math.max(titleHeight, icon.getImageData().height);
- }
-
- gc.setClipping((Region) null);
-
- return titleHeight;
- }
-
- /**
- * Notifies that the preview's configuration has changed.
- *
- * @param flags the change flags, a bitmask corresponding to the
- * {@code CHANGE_} constants in {@link ConfigurationClient}
- */
- public void configurationChanged(int flags) {
- if (!mVisible) {
- mDirty |= flags;
- return;
- }
-
- if ((flags & MASK_RENDERING) != 0) {
- mResourceResolver.clear();
- // Handle inheritance
- mConfiguration.syncFolderConfig();
- updateForkStatus();
- updateSize();
- }
-
- // Sanity check to make sure things are working correctly
- if (DEBUG) {
- RenderPreviewMode mode = mManager.getMode();
- if (mode == DEFAULT) {
- assert mConfiguration instanceof VaryingConfiguration;
- VaryingConfiguration config = (VaryingConfiguration) mConfiguration;
- int alternateFlags = config.getAlternateFlags();
- switch (alternateFlags) {
- case Configuration.CFG_DEVICE_STATE: {
- State configState = config.getDeviceState();
- State chooserState = mManager.getChooser().getConfiguration()
- .getDeviceState();
- assert configState != null && chooserState != null;
- assert !configState.getName().equals(chooserState.getName())
- : configState.toString() + ':' + chooserState;
-
- Device configDevice = config.getDevice();
- Device chooserDevice = mManager.getChooser().getConfiguration()
- .getDevice();
- assert configDevice != null && chooserDevice != null;
- assert configDevice == chooserDevice
- : configDevice.toString() + ':' + chooserDevice;
-
- break;
- }
- case Configuration.CFG_DEVICE: {
- Device configDevice = config.getDevice();
- Device chooserDevice = mManager.getChooser().getConfiguration()
- .getDevice();
- assert configDevice != null && chooserDevice != null;
- assert configDevice != chooserDevice
- : configDevice.toString() + ':' + chooserDevice;
-
- State configState = config.getDeviceState();
- State chooserState = mManager.getChooser().getConfiguration()
- .getDeviceState();
- assert configState != null && chooserState != null;
- assert configState.getName().equals(chooserState.getName())
- : configState.toString() + ':' + chooserState;
-
- break;
- }
- case Configuration.CFG_LOCALE: {
- Locale configLocale = config.getLocale();
- Locale chooserLocale = mManager.getChooser().getConfiguration()
- .getLocale();
- assert configLocale != null && chooserLocale != null;
- assert configLocale != chooserLocale
- : configLocale.toString() + ':' + chooserLocale;
- break;
- }
- default: {
- // Some other type of override I didn't anticipate
- assert false : alternateFlags;
- }
- }
- }
- }
-
- mDirty = 0;
- mManager.scheduleRender(this);
- }
-
- private void updateSize() {
- Device device = mConfiguration.getDevice();
- if (device == null) {
- return;
- }
- Screen screen = device.getDefaultHardware().getScreen();
- if (screen == null) {
- return;
- }
-
- FolderConfiguration folderConfig = mConfiguration.getFullConfig();
- ScreenOrientationQualifier qualifier = folderConfig.getScreenOrientationQualifier();
- ScreenOrientation orientation = qualifier == null
- ? ScreenOrientation.PORTRAIT : qualifier.getValue();
-
- // compute width and height to take orientation into account.
- int x = screen.getXDimension();
- int y = screen.getYDimension();
- int screenWidth, screenHeight;
-
- if (x > y) {
- if (orientation == ScreenOrientation.LANDSCAPE) {
- screenWidth = x;
- screenHeight = y;
- } else {
- screenWidth = y;
- screenHeight = x;
- }
- } else {
- if (orientation == ScreenOrientation.LANDSCAPE) {
- screenWidth = y;
- screenHeight = x;
- } else {
- screenWidth = x;
- screenHeight = y;
- }
- }
-
- int width = RenderPreviewManager.getMaxWidth();
- int height = RenderPreviewManager.getMaxHeight();
- if (screenWidth > 0) {
- double scale = getScale(screenWidth, screenHeight);
- width = (int) (screenWidth * scale);
- height = (int) (screenHeight * scale);
- }
-
- if (width != mWidth || height != mHeight) {
- mWidth = width;
- mHeight = height;
-
- Image thumbnail = mThumbnail;
- mThumbnail = null;
- if (thumbnail != null) {
- thumbnail.dispose();
- }
- if (mHeight != 0) {
- mAspectRatio = mWidth / (double) mHeight;
- }
- }
- }
-
- /**
- * Returns the configuration associated with this preview
- *
- * @return the configuration
- */
- @NonNull
- public Configuration getConfiguration() {
- return mConfiguration;
- }
-
- // ---- Implements IJobChangeListener ----
-
- @Override
- public void aboutToRun(IJobChangeEvent event) {
- }
-
- @Override
- public void awake(IJobChangeEvent event) {
- }
-
- @Override
- public void done(IJobChangeEvent event) {
- mJob = null;
- }
-
- @Override
- public void running(IJobChangeEvent event) {
- }
-
- @Override
- public void scheduled(IJobChangeEvent event) {
- }
-
- @Override
- public void sleeping(IJobChangeEvent event) {
- }
-
- // ---- Delayed Rendering ----
-
- private final class RenderJob extends UIJob {
- public RenderJob() {
- super("RenderPreview");
- setSystem(true);
- setUser(false);
- }
-
- @Override
- public IStatus runInUIThread(IProgressMonitor monitor) {
- mJob = null;
- if (!mCanvas.isDisposed()) {
- renderSync();
- mCanvas.redraw();
- return org.eclipse.core.runtime.Status.OK_STATUS;
- }
-
- return org.eclipse.core.runtime.Status.CANCEL_STATUS;
- }
-
- @Override
- public Display getDisplay() {
- if (mCanvas.isDisposed()) {
- return null;
- }
- return mCanvas.getDisplay();
- }
- }
-
- private final class AsyncRenderJob extends Job {
- public AsyncRenderJob() {
- super("RenderPreview");
- setSystem(true);
- setUser(false);
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- mJob = null;
-
- if (mCanvas.isDisposed()) {
- return org.eclipse.core.runtime.Status.CANCEL_STATUS;
- }
-
- renderSync();
-
- // Update display
- mCanvas.getDisplay().asyncExec(new Runnable() {
- @Override
- public void run() {
- mCanvas.redraw();
- }
- });
-
- return org.eclipse.core.runtime.Status.OK_STATUS;
- }
- }
-
- /**
- * Sets the input file to use for rendering. If not set, this will just be
- * the same file as the configuration chooser. This is used to render other
- * layouts, such as variations of the currently edited layout, which are
- * not kept in sync with the main layout.
- *
- * @param file the file to set as input
- */
- public void setAlternateInput(@Nullable IFile file) {
- mAlternateInput = file;
- }
-
- /** Corresponding description for this preview if it is a manually added preview */
- private @Nullable ConfigurationDescription mDescription;
-
- /**
- * Sets the description of this preview, if this preview is a manually added preview
- *
- * @param description the description of this preview
- */
- public void setDescription(@Nullable ConfigurationDescription description) {
- mDescription = description;
- }
-
- /**
- * Returns the description of this preview, if this preview is a manually added preview
- *
- * @return the description
- */
- @Nullable
- public ConfigurationDescription getDescription() {
- return mDescription;
- }
-
- @Override
- public String toString() {
- return getDisplayName() + ':' + mConfiguration;
- }
-
- /** Sorts render previews into increasing aspect ratio order */
- static Comparator<RenderPreview> INCREASING_ASPECT_RATIO = new Comparator<RenderPreview>() {
- @Override
- public int compare(RenderPreview preview1, RenderPreview preview2) {
- return (int) Math.signum(preview1.mAspectRatio - preview2.mAspectRatio);
- }
- };
- /** Sorts render previews into visual order: row by row, column by column */
- static Comparator<RenderPreview> VISUAL_ORDER = new Comparator<RenderPreview>() {
- @Override
- public int compare(RenderPreview preview1, RenderPreview preview2) {
- int delta = preview1.mY - preview2.mY;
- if (delta == 0) {
- delta = preview1.mX - preview2.mX;
- }
- return delta;
- }
- };
-}