// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.debug.ui.actions; import java.util.Iterator; import java.util.List; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionDelegate2; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; /** * A base class for actions. User implementation is responsible * for getting elements from context (i.e. selection) and for performing the action itself. * This class implements all methods of {@link IObjectActionDelegate} and {@link IActionDelegate2}. * @param <S> user type for data that is read from selection */ public abstract class SelectionBasedAction<S> implements IObjectActionDelegate, IActionDelegate2 { /** * Base class for actions that are enabled only for a single element in selection. * User implements {@link #castElement(Object)} method that map raw selection object * to a custom type T. Action optionally may allow selections with more than 1 object, * but it is required that only a single object is filtered out. */ public static abstract class Single<T> extends SelectionBasedAction<T> { private final boolean allowMutipleSelection; /** * @param allowMutipleSelection if false requires that selection contains exactly 1 element; * if true only requires that selection contains exactly 1 element that gets cast * by {@link #castElement(Object)} method */ protected Single(boolean allowMutipleSelection) { this.allowMutipleSelection = allowMutipleSelection; } @Override protected T readSelection(IStructuredSelection selection) { if (!allowMutipleSelection && selection.size() != 1) { return null; } T result = null; for (Iterator<?> it = selection.iterator(); it.hasNext(); ) { Object element = it.next(); T userElement = castElement(element); if (userElement == null) { continue; } if (result != null) { return null; } result = userElement; } return result; } /** * User-provided method that casts raw selection element to user type T. Method * may return null which means that this raw object should be ignored. */ protected abstract T castElement(Object element); } /** * Base class for actions that works with any number of elements in selection. */ static abstract class Multiple<T> extends SelectionBasedAction<List<? extends T>> { } private ActionRunnable currentRunnable = null; private Shell currentShell = null; private String originalActionText = null; private IWorkbenchPart currentTargetPart = null; private IAction action; protected abstract S readSelection(IStructuredSelection selection); public void setActivePart(IAction action, IWorkbenchPart targetPart) { currentShell = targetPart.getSite().getShell(); currentTargetPart = targetPart; } public void run(IAction action) { assert action == getAction(); if (currentRunnable == null) { return; } currentRunnable.run(currentShell, currentTargetPart); currentRunnable = null; } public void selectionChanged(IAction actionParam, ISelection selection) { currentRunnable = createRunnableFromRawSelection(selection); this.action.setEnabled(currentRunnable != null); if (currentRunnable == null) { restoreActionText(); } else { currentRunnable.adjustAction(); } } private ActionRunnable createRunnableFromRawSelection(ISelection selection) { if (selection instanceof IStructuredSelection == false) { return null; } IStructuredSelection structured = (IStructuredSelection) selection; final S selectedElements = readSelection(structured); return createRunnable(selectedElements); } protected abstract ActionRunnable createRunnable(S selectedElements); protected interface ActionRunnable { void adjustAction(); void run(Shell shell, IWorkbenchPart workbenchPart); } protected void modifyActionText(String newText) { if (originalActionText == null) { originalActionText = action.getText(); } action.setText(newText); } protected void restoreActionText() { if (originalActionText != null) { action.setText(originalActionText); originalActionText = null; } } protected IAction getAction() { return action; } public void dispose() { currentRunnable = null; } public void init(IAction action) { this.action = action; } public void runWithEvent(IAction action, Event event) { run(action); } }