blob: a7a9651322a5753c41f10e31890eff23f4d7c37f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Eric Rizzo - replaced Collapse All action with generic equivalent
*******************************************************************************/
package org.eclipse.jdt.internal.ui.packageview;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.actions.OpenInNewWindowAction;
import org.eclipse.ui.handlers.CollapseAllHandler;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.views.framelist.BackAction;
import org.eclipse.ui.views.framelist.ForwardAction;
import org.eclipse.ui.views.framelist.Frame;
import org.eclipse.ui.views.framelist.FrameAction;
import org.eclipse.ui.views.framelist.FrameList;
import org.eclipse.ui.views.framelist.GoIntoAction;
import org.eclipse.ui.views.framelist.TreeFrame;
import org.eclipse.ui.views.framelist.UpAction;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.IContextMenuConstants;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.actions.BuildActionGroup;
import org.eclipse.jdt.ui.actions.CCPActionGroup;
import org.eclipse.jdt.ui.actions.CustomFiltersActionGroup;
import org.eclipse.jdt.ui.actions.GenerateActionGroup;
import org.eclipse.jdt.ui.actions.ImportActionGroup;
import org.eclipse.jdt.ui.actions.JavaSearchActionGroup;
import org.eclipse.jdt.ui.actions.JdtActionConstants;
import org.eclipse.jdt.ui.actions.NavigateActionGroup;
import org.eclipse.jdt.ui.actions.OpenProjectAction;
import org.eclipse.jdt.ui.actions.ProjectActionGroup;
import org.eclipse.jdt.ui.actions.RefactorActionGroup;
import org.eclipse.jdt.internal.ui.actions.CollapseAllAction;
import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
import org.eclipse.jdt.internal.ui.actions.NewWizardsActionGroup;
import org.eclipse.jdt.internal.ui.actions.SelectAllAction;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.GenerateBuildPathActionGroup;
import org.eclipse.jdt.internal.ui.workingsets.ViewActionGroup;
class PackageExplorerActionGroup extends CompositeActionGroup {
private static final String FRAME_ACTION_SEPARATOR_ID= "FRAME_ACTION_SEPARATOR_ID"; //$NON-NLS-1$
private static final String FRAME_ACTION_GROUP_ID= "FRAME_ACTION_GROUP_ID"; //$NON-NLS-1$
private PackageExplorerPart fPart;
private FrameList fFrameList;
private GoIntoAction fZoomInAction;
private BackAction fBackAction;
private ForwardAction fForwardAction;
private UpAction fUpAction;
private boolean fFrameActionsShown;
private GotoTypeAction fGotoTypeAction;
private GotoPackageAction fGotoPackageAction;
private GotoResourceAction fGotoResourceAction;
private CollapseAllAction fCollapseAllAction;
private SelectAllAction fSelectAllAction;
private ToggleLinkingAction fToggleLinkingAction;
private RefactorActionGroup fRefactorActionGroup;
private NavigateActionGroup fNavigateActionGroup;
private ViewActionGroup fViewActionGroup;
private CustomFiltersActionGroup fCustomFiltersActionGroup;
private IAction fGotoRequiredProjectAction;
private ProjectActionGroup fProjectActionGroup;
public PackageExplorerActionGroup(PackageExplorerPart part) {
super();
fPart= part;
fFrameActionsShown= false;
TreeViewer viewer= part.getTreeViewer();
IPropertyChangeListener workingSetListener= event -> doWorkingSetChanged(event);
IWorkbenchPartSite site = fPart.getSite();
setGroups(new ActionGroup[] {
new NewWizardsActionGroup(site),
fNavigateActionGroup= new NavigateActionGroup(fPart),
new CCPActionGroup(fPart),
new GenerateBuildPathActionGroup(fPart),
new GenerateActionGroup(fPart),
fRefactorActionGroup= new RefactorActionGroup(fPart),
new ImportActionGroup(fPart),
new BuildActionGroup(fPart),
new JavaSearchActionGroup(fPart),
fProjectActionGroup= new ProjectActionGroup(fPart),
fViewActionGroup= new ViewActionGroup(fPart.getRootMode(), workingSetListener, site),
fCustomFiltersActionGroup= new CustomFiltersActionGroup(fPart, viewer),
new LayoutActionGroup(fPart)
});
fViewActionGroup.fillFilters(viewer);
PackagesFrameSource frameSource= new PackagesFrameSource(fPart);
fFrameList= new FrameList(frameSource);
frameSource.connectTo(fFrameList);
fZoomInAction= new GoIntoAction(fFrameList);
fPart.getSite().getSelectionProvider().addSelectionChangedListener(event -> fZoomInAction.update());
fBackAction= new BackAction(fFrameList);
fForwardAction= new ForwardAction(fFrameList);
fUpAction= new UpAction(fFrameList);
fFrameList.addPropertyChangeListener(event -> {
fPart.updateTitle();
fPart.updateToolbar();
});
fGotoTypeAction= new GotoTypeAction(fPart);
fGotoPackageAction= new GotoPackageAction(fPart);
fGotoResourceAction= new GotoResourceAction(fPart);
fCollapseAllAction= new CollapseAllAction(fPart.getTreeViewer());
fCollapseAllAction.setActionDefinitionId(CollapseAllHandler.COMMAND_ID);
fToggleLinkingAction = new ToggleLinkingAction(fPart);
fToggleLinkingAction.setActionDefinitionId(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR);
fGotoRequiredProjectAction= new GotoRequiredProjectAction(fPart);
fSelectAllAction= new SelectAllAction(fPart.getTreeViewer());
}
@Override
public void dispose() {
super.dispose();
}
//---- Persistent state -----------------------------------------------------------------------
/* package */ void restoreFilterAndSorterState(IMemento memento) {
fViewActionGroup.restoreState(memento);
fCustomFiltersActionGroup.restoreState(memento);
}
/* package */ void saveFilterAndSorterState(IMemento memento) {
fViewActionGroup.saveState(memento);
fCustomFiltersActionGroup.saveState(memento);
}
//---- Action Bars ----------------------------------------------------------------------------
@Override
public void fillActionBars(IActionBars actionBars) {
super.fillActionBars(actionBars);
setGlobalActionHandlers(actionBars);
fillToolBar(actionBars.getToolBarManager());
fillViewMenu(actionBars.getMenuManager());
}
private void setGlobalActionHandlers(IActionBars actionBars) {
// Navigate Go Into and Go To actions.
actionBars.setGlobalActionHandler(IWorkbenchActionConstants.GO_INTO, fZoomInAction);
actionBars.setGlobalActionHandler(ActionFactory.BACK.getId(), fBackAction);
actionBars.setGlobalActionHandler(ActionFactory.FORWARD.getId(), fForwardAction);
actionBars.setGlobalActionHandler(IWorkbenchActionConstants.UP, fUpAction);
actionBars.setGlobalActionHandler(IWorkbenchActionConstants.GO_TO_RESOURCE, fGotoResourceAction);
actionBars.setGlobalActionHandler(JdtActionConstants.GOTO_TYPE, fGotoTypeAction);
actionBars.setGlobalActionHandler(JdtActionConstants.GOTO_PACKAGE, fGotoPackageAction);
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction);
fRefactorActionGroup.retargetFileMenuActions(actionBars);
IHandlerService handlerService= fPart.getViewSite().getService(IHandlerService.class);
handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR, new ActionHandler(fToggleLinkingAction));
handlerService.activateHandler(CollapseAllHandler.COMMAND_ID, new ActionHandler(fCollapseAllAction));
}
/* package */ void fillToolBar(IToolBarManager toolBar) {
if (fBackAction.isEnabled() || fUpAction.isEnabled() || fForwardAction.isEnabled()) {
toolBar.add(fBackAction);
toolBar.add(fForwardAction);
toolBar.add(fUpAction);
toolBar.add(new Separator(FRAME_ACTION_SEPARATOR_ID));
fFrameActionsShown= true;
}
toolBar.add(new GroupMarker(FRAME_ACTION_GROUP_ID));
toolBar.add(fCollapseAllAction);
toolBar.add(fToggleLinkingAction);
toolBar.update(true);
}
public void updateToolBar(IToolBarManager toolBar) {
boolean hasBeenFrameActionsShown= fFrameActionsShown;
fFrameActionsShown= fBackAction.isEnabled() || fUpAction.isEnabled() || fForwardAction.isEnabled();
if (fFrameActionsShown != hasBeenFrameActionsShown) {
if (hasBeenFrameActionsShown) {
toolBar.remove(fBackAction.getId());
toolBar.remove(fForwardAction.getId());
toolBar.remove(fUpAction.getId());
toolBar.remove(FRAME_ACTION_SEPARATOR_ID);
} else {
toolBar.prependToGroup(FRAME_ACTION_GROUP_ID, new Separator(FRAME_ACTION_SEPARATOR_ID));
toolBar.prependToGroup(FRAME_ACTION_GROUP_ID, fUpAction);
toolBar.prependToGroup(FRAME_ACTION_GROUP_ID, fForwardAction);
toolBar.prependToGroup(FRAME_ACTION_GROUP_ID, fBackAction);
}
toolBar.update(true);
}
}
/* package */ void fillViewMenu(IMenuManager menu) {
menu.add(new Separator());
menu.add(fToggleLinkingAction);
menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));//$NON-NLS-1$
}
//---- Context menu -------------------------------------------------------------------------
@Override
public void fillContextMenu(IMenuManager menu) {
IStructuredSelection selection= (IStructuredSelection)getContext().getSelection();
int size= selection.size();
Object element= selection.getFirstElement();
if (element instanceof ClassPathContainer.RequiredProjectWrapper)
menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fGotoRequiredProjectAction);
addGotoMenu(menu, element, size);
addOpenNewWindowAction(menu, element);
super.fillContextMenu(menu);
}
private void addGotoMenu(IMenuManager menu, Object element, int size) {
boolean enabled= size == 1 && fPart.getTreeViewer().isExpandable(element) && (isGoIntoTarget(element) || element instanceof IContainer);
fZoomInAction.setEnabled(enabled);
if (enabled)
menu.appendToGroup(IContextMenuConstants.GROUP_GOTO, fZoomInAction);
}
private boolean isGoIntoTarget(Object element) {
if (element == null)
return false;
if (element instanceof IJavaElement) {
int type= ((IJavaElement)element).getElementType();
return type == IJavaElement.JAVA_PROJECT ||
type == IJavaElement.PACKAGE_FRAGMENT_ROOT ||
type == IJavaElement.PACKAGE_FRAGMENT;
}
if (element instanceof IWorkingSet) {
return true;
}
return false;
}
private void addOpenNewWindowAction(IMenuManager menu, Object element) {
if (element instanceof IJavaElement) {
element= ((IJavaElement)element).getResource();
}
// fix for 64890 Package explorer out of sync when open/closing projects [package explorer] 64890
if (element instanceof IProject && !((IProject)element).isOpen())
return;
if (!(element instanceof IContainer))
return;
menu.appendToGroup(
IContextMenuConstants.GROUP_OPEN,
new OpenInNewWindowAction(fPart.getSite().getWorkbenchWindow(), (IContainer)element));
}
//---- Key board and mouse handling ------------------------------------------------------------
/* package*/ void handleDoubleClick(DoubleClickEvent event) {
TreeViewer viewer= fPart.getTreeViewer();
IStructuredSelection selection= (IStructuredSelection)event.getSelection();
Object element= selection.getFirstElement();
if (viewer.isExpandable(element)) {
if (doubleClickGoesInto()) {
// don't zoom into compilation units and class files
if (element instanceof ICompilationUnit || element instanceof IClassFile)
return;
if (element instanceof IOpenable || element instanceof IContainer || element instanceof IWorkingSet) {
fZoomInAction.run();
}
} else {
IAction openAction= fNavigateActionGroup.getOpenAction();
if (openAction != null && openAction.isEnabled() && OpenStrategy.getOpenMethod() == OpenStrategy.DOUBLE_CLICK)
return;
if (selection instanceof ITreeSelection) {
for (TreePath path : ((ITreeSelection)selection).getPathsFor(element)) {
viewer.setExpandedState(path, !viewer.getExpandedState(path));
}
} else {
viewer.setExpandedState(element, !viewer.getExpandedState(element));
}
}
} else if (element instanceof IProject && !((IProject) element).isOpen()) {
OpenProjectAction openProjectAction= fProjectActionGroup.getOpenProjectAction();
if (openProjectAction.isEnabled()) {
openProjectAction.run();
}
}
}
/**
* Called by Package Explorer.
*
* @param event the open event
* @param activate <code>true</code> if the opened editor should be activated
*/
/* package */void handleOpen(ISelection event, boolean activate) {
IAction openAction= fNavigateActionGroup.getOpenAction();
if (openAction != null && openAction.isEnabled()) {
// XXX: should use the given arguments instead of using org.eclipse.jface.util.OpenStrategy.activateOnOpen()
openAction.run();
return;
}
}
/* package */ void handleKeyEvent(KeyEvent event) {
if (event.stateMask != 0)
return;
if (event.keyCode == SWT.BS) {
if (fUpAction != null && fUpAction.isEnabled()) {
fUpAction.run();
event.doit= false;
}
}
}
private void doWorkingSetChanged(PropertyChangeEvent event) {
if (ViewActionGroup.MODE_CHANGED.equals(event.getProperty())) {
fPart.rootModeChanged(((Integer)event.getNewValue()).intValue());
Object oldInput= null;
Object newInput= null;
if (fPart.getRootMode() == PackageExplorerPart.PROJECTS_AS_ROOTS) {
oldInput= fPart.getWorkingSetModel();
newInput= JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
} else {
oldInput= JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
newInput= fPart.getWorkingSetModel();
}
if (oldInput != null && newInput != null) {
Frame frame;
for (int i= 0; (frame= fFrameList.getFrame(i)) != null; i++) {
if (frame instanceof TreeFrame) {
TreeFrame treeFrame= (TreeFrame)frame;
if (oldInput.equals(treeFrame.getInput()))
treeFrame.setInput(newInput);
}
}
}
} else {
IWorkingSet workingSet= (IWorkingSet) event.getNewValue();
String workingSetLabel= null;
if (workingSet != null)
workingSetLabel= BasicElementLabels.getWorkingSetLabel(workingSet);
fPart.setWorkingSetLabel(workingSetLabel);
fPart.updateTitle();
String property= event.getProperty();
if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE.equals(property)) {
TreeViewer viewer= fPart.getTreeViewer();
viewer.getControl().setRedraw(false);
viewer.refresh();
viewer.getControl().setRedraw(true);
}
}
}
private boolean doubleClickGoesInto() {
return PreferenceConstants.DOUBLE_CLICK_GOES_INTO.equals(PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.DOUBLE_CLICK));
}
public FrameAction getUpAction() {
return fUpAction;
}
public FrameAction getBackAction() {
return fBackAction;
}
public FrameAction getForwardAction() {
return fForwardAction;
}
public ViewActionGroup getWorkingSetActionGroup() {
return fViewActionGroup;
}
public CustomFiltersActionGroup getCustomFilterActionGroup() {
return fCustomFiltersActionGroup;
}
public FrameList getFrameList() {
return fFrameList;
}
}