/******************************************************************************* * Copyright (c) 2012, 2014 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.ui.breakpoints; import java.util.Iterator; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.internal.ui.breakpoints.CBreakpointContext; import org.eclipse.core.runtime.Assert; import org.eclipse.debug.ui.contexts.IDebugContextProvider; import org.eclipse.jface.preference.IPreferenceNode; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.IShellProvider; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.SelectionProviderAction; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.internal.IWorkbenchHelpContextIds; import org.eclipse.ui.internal.WorkbenchMessages; /** * Action for opening a Property Pages Dialog on the C breakpoint object * in the currently selected element. * <p> * Generally speaking, this action is useful in pop-up menus because it allows * the user to browse and change properties of selected elements. When * performed, the action will bring up a Property Pages Dialog containing * property pages registered with the workbench for elements of the selected * type. * </p> * <p> * Although the action is capable of calculating if there are any applicable * pages for the current selection, this calculation is costly because it * require searching the workbench registry. Where performance is critical, the * action can simply be added to the pop-up menu. In the event of no applicable * pages, the action will just open an appropriate message dialog. * </p> * @noextend This class is not intended to be subclassed by clients. * @since 7.2 */ public class CBreakpointPropertyDialogAction extends SelectionProviderAction { /** * Provides the shell in which to open the property dialog. */ private IShellProvider fShellProvider; private IDebugContextProvider fDebugContextProvider; static final String PAGE_ID_COMMON = "org.eclipse.cdt.debug.ui.propertypages.breakpoint.common"; //$NON-NLS-1$ public CBreakpointPropertyDialogAction(IShellProvider shell, ISelectionProvider selectionProvider, IDebugContextProvider debugContextProvider) { super(selectionProvider, WorkbenchMessages.PropertyDialog_text); Assert.isNotNull(shell); fDebugContextProvider = debugContextProvider; fShellProvider = shell; setToolTipText(WorkbenchMessages.PropertyDialog_toolTip); PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IWorkbenchHelpContextIds.PROPERTY_DIALOG_ACTION); } protected ISelection getDebugContext() { return fDebugContextProvider.getActiveContext(); } /** * Returns whether this action is actually applicable to the current * selection. If this action is disabled, it will return <code>false</code> * without further calculation. If it is enabled, it will check with the * workbench's property page manager to see if there are any property pages * registered for the selected element's type. * <p> * This method is generally too expensive to use when updating the enabled * state of the action on each selection change. * </p> * * @return <code>true</code> if the selection is not empty and there are * property pages for the selected element, and <code>false</code> * otherwise */ public boolean isCBreakpointSelection() { if (!isEnabled()) { return false; } return isApplicableForSelection(getStructuredSelection(), getDebugContext()); } /** * Returns whether this action is applicable to the current selection. This * checks that the selection is not empty, and checks with the workbench's * property page manager to see if there are any property pages registered * for the selected element's type. * <p> * This method is generally too expensive to use when updating the enabled * state of the action on each selection change. * </p> * * @param selection * The selection to test * @return <code>true</code> if the selection is of not empty and there are * property pages for the selected element, and <code>false</code> * otherwise */ public boolean isApplicableForSelection(IStructuredSelection selection, ISelection debugContext) { return isCBreakpointSelection(selection); } /** * Returns whether the given selection contains only elements of type ICBreakpoint * @param selection * @return */ private boolean isCBreakpointSelection(IStructuredSelection selection) { if (selection.isEmpty()) return false; for (Iterator<?> itr = selection.iterator(); itr.hasNext();) { if ( !(itr.next() instanceof ICBreakpoint) ) { return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.jface.action.IAction#run() */ public void run() { CBreakpointContext bpContext = getCBreakpointContext(); if (bpContext != null) { PreferenceDialog dialog = createDialog(bpContext); if (dialog != null) { TreeViewer viewer = dialog.getTreeViewer(); if (viewer != null) { viewer.setComparator(new ViewerComparator() { @Override public int category(Object element) { if (element instanceof IPreferenceNode) { IPreferenceNode node = (IPreferenceNode)element; if ( PAGE_ID_COMMON.equals(node.getId()) ) { return 0; } else if (node.getSubNodes() == null || node.getSubNodes().length == 0) { // Pages without children (not categories) return super.category(element) + 1; } } // Categories last. return super.category(element) + 2; } }); // Expand all categories viewer.expandToLevel(TreeViewer.ALL_LEVELS); } dialog.open(); } } } private CBreakpointContext getCBreakpointContext() { IStructuredSelection ss = getStructuredSelection(); if (ss.size() >= 1 && ss.getFirstElement() instanceof ICBreakpoint) { return new CBreakpointContext((ICBreakpoint)ss.getFirstElement(), fDebugContextProvider.getActiveContext()); } return null; } /** * Create the dialog for the receiver. If no pages are found, an informative * message dialog is presented instead. * * @return PreferenceDialog or <code>null</code> if no applicable pages * are found. */ protected PreferenceDialog createDialog(CBreakpointContext bpContext) { IStructuredSelection ss = getStructuredSelection(); if (ss.isEmpty()) return null; String initialPageId = null; if (bpContext.getBreakpoint().getMarker() == null) { // Bug 433308 - Always show Common page initially for new breakpoints initialPageId = PAGE_ID_COMMON; } return PreferencesUtil.createPropertyDialogOn(fShellProvider.getShell(), bpContext, initialPageId, null, null); } /* (non-Javadoc) * @see org.eclipse.ui.actions.SelectionProviderAction#selectionChanged(org.eclipse.jface.viewers.IStructuredSelection) */ public void selectionChanged(IStructuredSelection selection) { setEnabled(!selection.isEmpty()); } }