Home | History | Annotate | Download | only in gle2
      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.editors.layout.gle2;
     17 
     18 import static com.android.SdkConstants.FD_RESOURCES;
     19 import static com.android.SdkConstants.FD_RES_ANIMATOR;
     20 import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
     21 
     22 import com.android.ide.common.rendering.api.Capability;
     23 import com.android.ide.common.rendering.api.IAnimationListener;
     24 import com.android.ide.common.rendering.api.RenderSession;
     25 import com.android.ide.common.rendering.api.Result;
     26 import com.android.ide.eclipse.adt.AdtPlugin;
     27 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
     28 import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileWizard;
     29 import com.android.resources.ResourceType;
     30 import com.android.utils.Pair;
     31 
     32 import org.eclipse.core.resources.IProject;
     33 import org.eclipse.jface.action.Action;
     34 import org.eclipse.jface.action.ActionContributionItem;
     35 import org.eclipse.jface.action.IAction;
     36 import org.eclipse.jface.action.Separator;
     37 import org.eclipse.jface.viewers.IStructuredSelection;
     38 import org.eclipse.jface.viewers.StructuredSelection;
     39 import org.eclipse.jface.wizard.WizardDialog;
     40 import org.eclipse.swt.widgets.Menu;
     41 import org.eclipse.swt.widgets.Shell;
     42 import org.eclipse.ui.IWorkbench;
     43 import org.eclipse.ui.IWorkbenchWindow;
     44 
     45 import java.util.ArrayList;
     46 import java.util.Collection;
     47 import java.util.Collections;
     48 import java.util.List;
     49 
     50 /**
     51  * "Play Animation" context menu which lists available animations in the project and in
     52  * the framework, as well as a "Create Animation" shortcut, and allows the animation to be
     53  * run on the selection
     54  * <p/>
     55  * TODO: Add transport controls for play/rewind/pause/loop, and (if possible) scrubbing
     56  */
     57 public class PlayAnimationMenu extends SubmenuAction {
     58     /** Associated canvas */
     59     private final LayoutCanvas mCanvas;
     60     /** Whether this menu is showing local animations or framework animations */
     61     private boolean mFramework;
     62 
     63     /**
     64      * Creates a "Play Animation" menu
     65      *
     66      * @param canvas associated canvas
     67      */
     68     public PlayAnimationMenu(LayoutCanvas canvas) {
     69         this(canvas, "Play Animation", false);
     70     }
     71 
     72     /**
     73      * Creates an animation menu; this can be used either for the outer Play animation
     74      * menu, or the inner frameworks-animations list
     75      *
     76      * @param canvas the associated canvas
     77      * @param title menu item name
     78      * @param framework true to show the framework animations, false for the project (and
     79      *            nested framework-animation-menu) animations
     80      */
     81     private PlayAnimationMenu(LayoutCanvas canvas, String title, boolean framework) {
     82         super(title);
     83         mCanvas = canvas;
     84         mFramework = framework;
     85     }
     86 
     87     @Override
     88     protected void addMenuItems(Menu menu) {
     89         SelectionManager selectionManager = mCanvas.getSelectionManager();
     90         List<SelectionItem> selection = selectionManager.getSelections();
     91         if (selection.size() != 1) {
     92             addDisabledMessageItem("Select exactly one widget");
     93             return;
     94         }
     95 
     96         GraphicalEditorPart graphicalEditor = mCanvas.getEditorDelegate().getGraphicalEditor();
     97         if (graphicalEditor.renderingSupports(Capability.PLAY_ANIMATION)) {
     98             // List of animations
     99             Collection<String> animationNames = graphicalEditor.getResourceNames(mFramework,
    100                     ResourceType.ANIMATOR);
    101             if (animationNames.size() > 0) {
    102                 // Sort alphabetically
    103                 List<String> sortedNames = new ArrayList<String>(animationNames);
    104                 Collections.sort(sortedNames);
    105 
    106                 for (String animation : sortedNames) {
    107                     String title = animation;
    108                     IAction action = new PlayAnimationAction(title, animation, mFramework);
    109                     new ActionContributionItem(action).fill(menu, -1);
    110                 }
    111 
    112                 new Separator().fill(menu, -1);
    113             }
    114 
    115             if (!mFramework) {
    116                 // Not in the framework submenu: include recent list and create new actions
    117 
    118                 // "Create New" action
    119                 new ActionContributionItem(new CreateAnimationAction()).fill(menu, -1);
    120 
    121                 // Framework resources submenu
    122                 new Separator().fill(menu, -1);
    123                 PlayAnimationMenu sub = new PlayAnimationMenu(mCanvas, "Android Builtin", true);
    124                 new ActionContributionItem(sub).fill(menu, -1);
    125             }
    126         } else {
    127             addDisabledMessageItem(
    128                     "Not supported for this SDK version; try changing the Render Target");
    129         }
    130     }
    131 
    132     private class PlayAnimationAction extends Action {
    133         private final String mAnimationName;
    134         private final boolean mIsFrameworkAnim;
    135 
    136         public PlayAnimationAction(String title, String animationName, boolean isFrameworkAnim) {
    137             super(title, IAction.AS_PUSH_BUTTON);
    138             mAnimationName = animationName;
    139             mIsFrameworkAnim = isFrameworkAnim;
    140         }
    141 
    142         @Override
    143         public void run() {
    144             SelectionManager selectionManager = mCanvas.getSelectionManager();
    145             List<SelectionItem> selection = selectionManager.getSelections();
    146             SelectionItem canvasSelection = selection.get(0);
    147             CanvasViewInfo info = canvasSelection.getViewInfo();
    148 
    149             Object viewObject = info.getViewObject();
    150             if (viewObject != null) {
    151                 ViewHierarchy viewHierarchy = mCanvas.getViewHierarchy();
    152                 RenderSession session = viewHierarchy.getSession();
    153                 Result r = session.animate(viewObject, mAnimationName, mIsFrameworkAnim,
    154                         new IAnimationListener() {
    155                             private boolean mPendingDrawing = false;
    156 
    157                             @Override
    158                             public void onNewFrame(RenderSession s) {
    159                                 SelectionOverlay selectionOverlay = mCanvas.getSelectionOverlay();
    160                                 if (!selectionOverlay.isHiding()) {
    161                                     selectionOverlay.setHiding(true);
    162                                 }
    163                                 HoverOverlay hoverOverlay = mCanvas.getHoverOverlay();
    164                                 if (!hoverOverlay.isHiding()) {
    165                                     hoverOverlay.setHiding(true);
    166                                 }
    167 
    168                                 ImageOverlay imageOverlay = mCanvas.getImageOverlay();
    169                                 imageOverlay.setImage(s.getImage(), s.isAlphaChannelImage());
    170                                 synchronized (this) {
    171                                     if (mPendingDrawing == false) {
    172                                         mCanvas.getDisplay().asyncExec(new Runnable() {
    173                                             @Override
    174                                             public void run() {
    175                                                 synchronized (this) {
    176                                                     mPendingDrawing = false;
    177                                                 }
    178                                                 mCanvas.redraw();
    179                                             }
    180                                         });
    181                                         mPendingDrawing = true;
    182                                     }
    183                                 }
    184                             }
    185 
    186                             @Override
    187                             public boolean isCanceled() {
    188                                 return false;
    189                             }
    190 
    191                             @Override
    192                             public void done(Result result) {
    193                                 SelectionOverlay selectionOverlay = mCanvas.getSelectionOverlay();
    194                                 selectionOverlay.setHiding(false);
    195                                 HoverOverlay hoverOverlay = mCanvas.getHoverOverlay();
    196                                 hoverOverlay.setHiding(false);
    197 
    198                                 // Must refresh view hierarchy to force objects back to
    199                                 // their original positions in case animations have left
    200                                 // them elsewhere
    201                                 mCanvas.getDisplay().asyncExec(new Runnable() {
    202                                     @Override
    203                                     public void run() {
    204                                         GraphicalEditorPart graphicalEditor = mCanvas
    205                                                 .getEditorDelegate().getGraphicalEditor();
    206                                         graphicalEditor.recomputeLayout();
    207                                     }
    208                                 });
    209                             }
    210                         });
    211 
    212                 if (!r.isSuccess()) {
    213                     if (r.getErrorMessage() != null) {
    214                         AdtPlugin.log(r.getException(), r.getErrorMessage());
    215                     }
    216                 }
    217             }
    218         }
    219     }
    220 
    221     /**
    222      * Action which brings up the "Create new XML File" wizard, pre-selected with the
    223      * animation category
    224      */
    225     private class CreateAnimationAction extends Action {
    226         public CreateAnimationAction() {
    227             super("Create...", IAction.AS_PUSH_BUTTON);
    228         }
    229 
    230         @Override
    231         public void run() {
    232             Shell parent = mCanvas.getShell();
    233             NewXmlFileWizard wizard = new NewXmlFileWizard();
    234             LayoutEditorDelegate editor = mCanvas.getEditorDelegate();
    235             IWorkbenchWindow workbenchWindow =
    236                 editor.getEditor().getEditorSite().getWorkbenchWindow();
    237             IWorkbench workbench = workbenchWindow.getWorkbench();
    238             String animationDir = FD_RESOURCES + WS_SEP + FD_RES_ANIMATOR;
    239             Pair<IProject, String> pair = Pair.of(editor.getEditor().getProject(), animationDir);
    240             IStructuredSelection selection = new StructuredSelection(pair);
    241             wizard.init(workbench, selection);
    242             WizardDialog dialog = new WizardDialog(parent, wizard);
    243             dialog.create();
    244             dialog.open();
    245         }
    246     }
    247 }
    248