blob: 629a42f188c72859d0060c00aa26183ba2146e43 [file] [log] [blame]
/*
* Copyright (C) 2011 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.FD_RESOURCES;
import static com.android.SdkConstants.FD_RES_ANIMATOR;
import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileWizard;
import com.android.resources.ResourceType;
import com.android.utils.Pair;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* "Play Animation" context menu which lists available animations in the project and in
* the framework, as well as a "Create Animation" shortcut, and allows the animation to be
* run on the selection
* <p/>
* TODO: Add transport controls for play/rewind/pause/loop, and (if possible) scrubbing
*/
public class PlayAnimationMenu extends SubmenuAction {
/** Associated canvas */
private final LayoutCanvas mCanvas;
/** Whether this menu is showing local animations or framework animations */
private boolean mFramework;
/**
* Creates a "Play Animation" menu
*
* @param canvas associated canvas
*/
public PlayAnimationMenu(LayoutCanvas canvas) {
this(canvas, "Play Animation", false);
}
/**
* Creates an animation menu; this can be used either for the outer Play animation
* menu, or the inner frameworks-animations list
*
* @param canvas the associated canvas
* @param title menu item name
* @param framework true to show the framework animations, false for the project (and
* nested framework-animation-menu) animations
*/
private PlayAnimationMenu(LayoutCanvas canvas, String title, boolean framework) {
super(title);
mCanvas = canvas;
mFramework = framework;
}
@Override
protected void addMenuItems(Menu menu) {
SelectionManager selectionManager = mCanvas.getSelectionManager();
List<SelectionItem> selection = selectionManager.getSelections();
if (selection.size() != 1) {
addDisabledMessageItem("Select exactly one widget");
return;
}
GraphicalEditorPart graphicalEditor = mCanvas.getEditorDelegate().getGraphicalEditor();
if (graphicalEditor.renderingSupports(Capability.PLAY_ANIMATION)) {
// List of animations
Collection<String> animationNames = graphicalEditor.getResourceNames(mFramework,
ResourceType.ANIMATOR);
if (animationNames.size() > 0) {
// Sort alphabetically
List<String> sortedNames = new ArrayList<String>(animationNames);
Collections.sort(sortedNames);
for (String animation : sortedNames) {
String title = animation;
IAction action = new PlayAnimationAction(title, animation, mFramework);
new ActionContributionItem(action).fill(menu, -1);
}
new Separator().fill(menu, -1);
}
if (!mFramework) {
// Not in the framework submenu: include recent list and create new actions
// "Create New" action
new ActionContributionItem(new CreateAnimationAction()).fill(menu, -1);
// Framework resources submenu
new Separator().fill(menu, -1);
PlayAnimationMenu sub = new PlayAnimationMenu(mCanvas, "Android Builtin", true);
new ActionContributionItem(sub).fill(menu, -1);
}
} else {
addDisabledMessageItem(
"Not supported for this SDK version; try changing the Render Target");
}
}
private class PlayAnimationAction extends Action {
private final String mAnimationName;
private final boolean mIsFrameworkAnim;
public PlayAnimationAction(String title, String animationName, boolean isFrameworkAnim) {
super(title, IAction.AS_PUSH_BUTTON);
mAnimationName = animationName;
mIsFrameworkAnim = isFrameworkAnim;
}
@Override
public void run() {
SelectionManager selectionManager = mCanvas.getSelectionManager();
List<SelectionItem> selection = selectionManager.getSelections();
SelectionItem canvasSelection = selection.get(0);
CanvasViewInfo info = canvasSelection.getViewInfo();
Object viewObject = info.getViewObject();
if (viewObject != null) {
ViewHierarchy viewHierarchy = mCanvas.getViewHierarchy();
RenderSession session = viewHierarchy.getSession();
Result r = session.animate(viewObject, mAnimationName, mIsFrameworkAnim,
new IAnimationListener() {
private boolean mPendingDrawing = false;
@Override
public void onNewFrame(RenderSession s) {
SelectionOverlay selectionOverlay = mCanvas.getSelectionOverlay();
if (!selectionOverlay.isHiding()) {
selectionOverlay.setHiding(true);
}
HoverOverlay hoverOverlay = mCanvas.getHoverOverlay();
if (!hoverOverlay.isHiding()) {
hoverOverlay.setHiding(true);
}
ImageOverlay imageOverlay = mCanvas.getImageOverlay();
imageOverlay.setImage(s.getImage(), s.isAlphaChannelImage());
synchronized (this) {
if (mPendingDrawing == false) {
mCanvas.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
synchronized (this) {
mPendingDrawing = false;
}
mCanvas.redraw();
}
});
mPendingDrawing = true;
}
}
}
@Override
public boolean isCanceled() {
return false;
}
@Override
public void done(Result result) {
SelectionOverlay selectionOverlay = mCanvas.getSelectionOverlay();
selectionOverlay.setHiding(false);
HoverOverlay hoverOverlay = mCanvas.getHoverOverlay();
hoverOverlay.setHiding(false);
// Must refresh view hierarchy to force objects back to
// their original positions in case animations have left
// them elsewhere
mCanvas.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
GraphicalEditorPart graphicalEditor = mCanvas
.getEditorDelegate().getGraphicalEditor();
graphicalEditor.recomputeLayout();
}
});
}
});
if (!r.isSuccess()) {
if (r.getErrorMessage() != null) {
AdtPlugin.log(r.getException(), r.getErrorMessage());
}
}
}
}
}
/**
* Action which brings up the "Create new XML File" wizard, pre-selected with the
* animation category
*/
private class CreateAnimationAction extends Action {
public CreateAnimationAction() {
super("Create...", IAction.AS_PUSH_BUTTON);
}
@Override
public void run() {
Shell parent = mCanvas.getShell();
NewXmlFileWizard wizard = new NewXmlFileWizard();
LayoutEditorDelegate editor = mCanvas.getEditorDelegate();
IWorkbenchWindow workbenchWindow =
editor.getEditor().getEditorSite().getWorkbenchWindow();
IWorkbench workbench = workbenchWindow.getWorkbench();
String animationDir = FD_RESOURCES + WS_SEP + FD_RES_ANIMATOR;
Pair<IProject, String> pair = Pair.of(editor.getEditor().getProject(), animationDir);
IStructuredSelection selection = new StructuredSelection(pair);
wizard.init(workbench, selection);
WizardDialog dialog = new WizardDialog(parent, wizard);
dialog.create();
dialog.open();
}
}
}