Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.ide.eclipse.adt.internal.ui;
     17 
     18 import static com.android.SdkConstants.DOT_9PNG;
     19 import static com.android.utils.SdkUtils.endsWithIgnoreCase;
     20 
     21 import com.android.ide.common.rendering.api.ResourceValue;
     22 import com.android.ide.common.resources.ResourceResolver;
     23 import com.android.ide.eclipse.adt.AdtPlugin;
     24 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
     25 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
     26 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
     27 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService;
     28 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils;
     29 import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
     30 import com.android.resources.ResourceType;
     31 
     32 import org.eclipse.core.runtime.IStatus;
     33 import org.eclipse.jface.dialogs.DialogTray;
     34 import org.eclipse.jface.dialogs.TrayDialog;
     35 import org.eclipse.swt.SWT;
     36 import org.eclipse.swt.graphics.RGB;
     37 import org.eclipse.swt.layout.GridData;
     38 import org.eclipse.swt.layout.GridLayout;
     39 import org.eclipse.swt.widgets.Composite;
     40 import org.eclipse.swt.widgets.Control;
     41 import org.eclipse.swt.widgets.Display;
     42 import org.eclipse.swt.widgets.Label;
     43 
     44 import java.awt.image.BufferedImage;
     45 import java.io.File;
     46 import java.io.IOException;
     47 
     48 import javax.imageio.ImageIO;
     49 
     50 /**
     51  * The {@link ResourcePreviewHelper} provides help to {@link TrayDialog} resource choosers
     52  * where some resources (such as drawables and colors) are previewed in the tray area.
     53  */
     54 public class ResourcePreviewHelper {
     55     /**
     56      * The width of the preview rendering
     57      * <p>
     58      * TODO: Make the preview rendering resize if the tray area is resized
     59      */
     60     private static final int WIDTH = 100;
     61     /** The height of the preview rendering */
     62     private static final int HEIGHT = 100;
     63 
     64     private final GraphicalEditorPart mEditor;
     65     private final TrayDialog mTrayDialog;
     66 
     67     private boolean mShowingPreview;
     68     private DialogTray mPreviewTray;
     69     private ImageControl mPreviewImageControl;
     70 
     71     /**
     72      * Constructs a new {@link ResourcePreviewHelper}.
     73      * <p>
     74      * TODO: Add support for performing previews without an associated graphical editor,
     75      * such as previewing icons from the manifest form editor; just pick default
     76      * configuration settings in that case.
     77      *
     78      * @param trayDialog the associated tray-capable dialog
     79      * @param editor a graphical editor. This is currently needed in order to provide
     80      *            configuration data for the rendering.
     81      */
     82     public ResourcePreviewHelper(TrayDialog trayDialog, GraphicalEditorPart editor) {
     83         this.mTrayDialog = trayDialog;
     84         this.mEditor = editor;
     85     }
     86 
     87     /**
     88      * Updates the preview based on the current selection and resource type, possibly
     89      * hiding or opening the tray in the process.
     90      *
     91      * @param type the resource type for the selected resource
     92      * @param resource the full resource url
     93      */
     94     public void updatePreview(ResourceType type, String resource) {
     95         boolean showPreview = type == ResourceType.DRAWABLE || type == ResourceType.COLOR;
     96         if (showPreview) {
     97             if (mPreviewTray == null) {
     98                 mPreviewTray = new DialogTray() {
     99                     @Override
    100                     protected Control createContents(Composite parent) {
    101                         // This creates a centered image control
    102                         Composite panel = new Composite(parent, SWT.NONE);
    103                         panel.setLayout(new GridLayout(3, false));
    104                         Label dummy1 = new Label(panel, SWT.NONE);
    105                         dummy1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 1, 1));
    106                         mPreviewImageControl = new ImageControl(panel, SWT.NONE, SwtUtils
    107                                 .createEmptyImage(parent.getDisplay(), WIDTH, HEIGHT));
    108                         GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
    109                         gd.widthHint = WIDTH;
    110                         gd.heightHint = HEIGHT;
    111                         mPreviewImageControl.setLayoutData(gd);
    112                         Label dummy2 = new Label(panel, SWT.NONE);
    113                         dummy2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 1, 1));
    114 
    115                         return panel;
    116                     }
    117 
    118                 };
    119             }
    120 
    121             if (!mShowingPreview) {
    122                 mTrayDialog.openTray(mPreviewTray);
    123             }
    124 
    125             BufferedImage image = null;
    126             try {
    127                 if (type == ResourceType.COLOR) {
    128                     ResourceResolver resources = mEditor.getResourceResolver();
    129                     ResourceValue value = resources.findResValue(resource, false);
    130                     if (value != null) {
    131                         RGB color = ResourceHelper.resolveColor(resources, value);
    132                         if (color != null) {
    133                             image = ImageUtils.createColoredImage(WIDTH, HEIGHT, color);
    134                         }
    135                     }
    136                 } else {
    137                     assert type == ResourceType.DRAWABLE;
    138 
    139                     ResourceResolver resources = mEditor.getResourceResolver();
    140                     ResourceValue drawable = resources.findResValue(resource, false);
    141                     if (drawable != null) {
    142                         String path = drawable.getValue();
    143 
    144                         // Special-case image files (other than 9-patch files) and render these
    145                         // directly, in order to provide proper aspect ratio handling and
    146                         // to handle scaling to show the full contents:
    147                         if (ImageUtils.hasImageExtension(path)
    148                                 && !endsWithIgnoreCase(path, DOT_9PNG)) {
    149                             File file = new File(path);
    150                             if (file.exists()) {
    151                                 try {
    152                                     image = ImageIO.read(file);
    153                                     int width = image.getWidth();
    154                                     int height = image.getHeight();
    155                                     if (width > WIDTH || height > HEIGHT) {
    156                                         double xScale = WIDTH / (double) width;
    157                                         double yScale = HEIGHT / (double) height;
    158                                         double scale = Math.min(xScale, yScale);
    159                                         image = ImageUtils.scale(image, scale, scale);
    160                                     }
    161                                 } catch (IOException e) {
    162                                     AdtPlugin.log(e, "Can't read preview image %1$s", path);
    163                                 }
    164                             }
    165                         }
    166 
    167                         if (image == null) {
    168                             RenderService renderService = RenderService.create(mEditor);
    169                             renderService.setOverrideRenderSize(WIDTH, HEIGHT);
    170                             image = renderService.renderDrawable(drawable);
    171                         }
    172                     }
    173                 }
    174             } catch (Throwable t) {
    175                 // Some kind of rendering error occurred. However, we don't want to use
    176                 //    AdtPlugin.log(t, "Can't generate preview for %1$s", resource);
    177                 // because if it's a severe type of error (such as an InternalError shown
    178                 // in issue #18623) then a dialog will pop up and interfere with the
    179                 // preview, so just log a warning (unfortunately without the trace) instead.
    180                 AdtPlugin.log(IStatus.WARNING, "Can't generate preview for %1$s", resource);
    181             }
    182 
    183             Display display = mEditor.getSite().getShell().getDisplay();
    184             if (image != null) {
    185                 mPreviewImageControl.setImage(SwtUtils.convertToSwt(display, image, true, -1));
    186             } else {
    187                 mPreviewImageControl.setImage(SwtUtils.createEmptyImage(display, WIDTH, HEIGHT));
    188             }
    189             mPreviewImageControl.redraw();
    190         } else if (mPreviewTray != null && mShowingPreview) {
    191             mTrayDialog.closeTray();
    192         }
    193         mShowingPreview = showPreview;
    194     }
    195 }
    196