blob: 9fb61fac788aa2616dff519fcca6994f0cbc3c97 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.refactoring.reorg;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tracker;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.bindings.keys.IKeyLookup;
import org.eclipse.jface.bindings.keys.KeyLookupFactory;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.IViewportListener;
import org.eclipse.jface.text.IWidgetTokenKeeper;
import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
import org.eclipse.jface.text.IWidgetTokenOwner;
import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jdt.internal.ui.preferences.JavaBasePreferencePage;
public class RenameInformationPopup implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
private class PopupVisibilityManager implements IPartListener2, ControlListener, MouseListener, KeyListener, ITextListener, IViewportListener {
public void start() {
fEditor.getSite().getWorkbenchWindow().getPartService().addPartListener(this);
final ISourceViewer viewer= fEditor.getViewer();
final StyledText textWidget= viewer.getTextWidget();
textWidget.addControlListener(this);
textWidget.addMouseListener(this);
textWidget.addKeyListener(this);
fEditor.getSite().getShell().addControlListener(this);
viewer.addTextListener(this);
viewer.addViewportListener(this);
fPopup.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
fEditor.getSite().getWorkbenchWindow().getPartService().removePartListener(PopupVisibilityManager.this);
if (! textWidget.isDisposed()) {
textWidget.removeControlListener(PopupVisibilityManager.this);
textWidget.removeMouseListener(PopupVisibilityManager.this);
textWidget.removeKeyListener(PopupVisibilityManager.this);
}
fEditor.getSite().getShell().removeControlListener(PopupVisibilityManager.this);
viewer.removeTextListener(PopupVisibilityManager.this);
viewer.removeViewportListener(PopupVisibilityManager.this);
if (fMenuImage != null) {
fMenuImage.dispose();
fMenuImage= null;
}
if (fMenuManager != null) {
fMenuManager.dispose();
fMenuManager= null;
}
fRenameLinkedMode.cancel();
}
});
}
public void partActivated(IWorkbenchPartReference partRef) {
IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
if (partRef.getPart(false) == fPart) {
updateVisibility();
}
}
public void partBroughtToTop(IWorkbenchPartReference partRef) {
}
public void partClosed(IWorkbenchPartReference partRef) {
}
public void partDeactivated(IWorkbenchPartReference partRef) {
IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
if (fPopup != null && ! fPopup.isDisposed() && partRef.getPart(false) == fPart) {
fPopup.setVisible(false);
}
}
public void partHidden(IWorkbenchPartReference partRef) {
}
public void partInputChanged(IWorkbenchPartReference partRef) {
}
public void partOpened(IWorkbenchPartReference partRef) {
}
public void partVisible(IWorkbenchPartReference partRef) {
}
public void controlMoved(ControlEvent e) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
public void controlResized(ControlEvent e) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
updatePopupLocation(false);
updateVisibility();
}
public void keyPressed(KeyEvent e) {
updatePopupLocation(false);
updateVisibility();
}
public void keyReleased(KeyEvent e) {
}
public void textChanged(TextEvent event) {
updatePopupLocation(false);
updateVisibility(); //only for hiding outside editor area
}
public void viewportChanged(int verticalOffset) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
}
/**
* Cached platform flags for dealing with platform-specific issues.
*/
private static boolean CARBON = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
private static final int WIDGET_PRIORITY= 1000;
private static final String DIALOG_SETTINGS_SECTION= "RenameInformationPopup"; //$NON-NLS-1$
private static final String SNAP_POSITION_KEY= "snap_position"; //$NON-NLS-1$
private static final int SNAP_POSITION_UNDER_RIGHT_FIELD= 0;
private static final int SNAP_POSITION_OVER_RIGHT_FIELD= 1;
private static final int SNAP_POSITION_UNDER_LEFT_FIELD= 2;
private static final int SNAP_POSITION_OVER_LEFT_FIELD= 3;
private static final int SNAP_POSITION_LOWER_RIGHT= 4;
private static final int POPUP_VISIBILITY_DELAY= 300;
/**
* Offset of info hover arrow from the left or right side.
*/
private static final int HAO= 10;
/**
* Width of info hover arrow.
*/
private static final int HAW= 8;
/**
* Height of info hover arrow.
*/
private static final int HAH= 10;
/**
* Gap between linked position and popup.
*/
private static final int GAP= 2;
private final CompilationUnitEditor fEditor;
private final RenameLinkedMode fRenameLinkedMode;
private int fSnapPosition;
private Shell fPopup;
private GridLayout fPopupLayout;
private Region fRegion;
private Image fMenuImage;
private MenuManager fMenuManager;
private ToolBar fToolBar;
private String fOpenDialogBinding= ""; //$NON-NLS-1$
private boolean fIsMenuUp= false;
private boolean fDelayJobFinished= false;
public RenameInformationPopup(CompilationUnitEditor editor, RenameLinkedMode renameLinkedMode) {
fEditor= editor;
fRenameLinkedMode= renameLinkedMode;
restoreSnapPosition();
}
private void restoreSnapPosition() {
IDialogSettings settings= getDialogSettings();
try {
fSnapPosition= settings.getInt(SNAP_POSITION_KEY);
} catch (NumberFormatException e) {
// default:
fSnapPosition= SNAP_POSITION_UNDER_LEFT_FIELD;
}
}
private IDialogSettings getDialogSettings() {
return JavaPlugin.getDefault().getDialogSettingsSection(DIALOG_SETTINGS_SECTION);
}
public void open() {
// Must cache here, since editor context is not available in menu from popup shell:
fOpenDialogBinding= getOpenDialogBinding();
Shell workbenchShell= fEditor.getSite().getShell();
final Display display= workbenchShell.getDisplay();
fPopup= new Shell(workbenchShell, SWT.ON_TOP | SWT.NO_TRIM | SWT.TOOL);
fPopupLayout= new GridLayout(2, false);
fPopupLayout.marginWidth= 1;
fPopupLayout.marginHeight= 1;
fPopupLayout.marginLeft= 4;
fPopupLayout.horizontalSpacing= 0;
fPopup.setLayout(fPopupLayout);
createContent(fPopup);
updatePopupLocation(true);
new PopupVisibilityManager().start();
// Leave linked mode when popup loses focus
// (except when focus goes back to workbench window or menu is open):
fPopup.addShellListener(new ShellAdapter() {
public void shellDeactivated(ShellEvent e) {
if (fIsMenuUp)
return;
final Shell editorShell= fEditor.getSite().getShell();
display.asyncExec(new Runnable() {
// post to UI thread since editor shell only gets activated after popup has lost focus
public void run() {
Shell activeShell= display.getActiveShell();
if (activeShell != editorShell) {
fRenameLinkedMode.cancel();
}
}
});
}
});
if (! CARBON) { // carbon draws its own border...
fPopup.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent pe) {
pe.gc.drawPolygon(getPolygon(true));
}
});
}
// fPopup.moveBelow(null); // make sure hovers are on top of the info popup
// XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
// fPopup.moveBelow(workbenchShell.getShells()[0]);
UIJob delayJob= new UIJob(display, ReorgMessages.RenameInformationPopup_delayJobName) {
public IStatus runInUIThread(IProgressMonitor monitor) {
fDelayJobFinished= true;
if (fPopup != null && ! fPopup.isDisposed()) {
updateVisibility();
}
return Status.OK_STATUS;
}
};
delayJob.setSystem(true);
delayJob.setPriority(Job.INTERACTIVE);
delayJob.schedule(POPUP_VISIBILITY_DELAY);
}
public void close() {
if (fPopup != null) {
if (!fPopup.isDisposed()) {
fPopup.close();
}
fPopup= null;
}
releaseWidgetToken();
if (fRegion != null) {
if (! fRegion.isDisposed()) {
fRegion.dispose();
}
}
}
public Shell getShell() {
return fPopup;
}
private void updatePopupLocation(boolean force) {
if (! force && fSnapPosition == SNAP_POSITION_LOWER_RIGHT)
return;
packPopup();
Point loc= computePopupLocation(fSnapPosition);
if (loc != null) {
fPopup.setLocation(loc);
// XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
// fPopup.moveBelow(fEditor.getSite().getShell().getShells()[0]);
}
}
private void updateVisibility() {
if (fPopup != null && !fPopup.isDisposed() && fDelayJobFinished) {
boolean visible= false;
//TODO: Check for visibility of linked position, not whether popup is outside of editor?
if (fRenameLinkedMode.isCaretInLinkedPosition()) {
StyledText textWidget= fEditor.getViewer().getTextWidget();
Rectangle eArea= Geometry.toDisplay(textWidget, textWidget.getClientArea());
Rectangle pBounds= fPopup.getBounds();
pBounds.x-= GAP;
pBounds.y-= GAP;
pBounds.width+= 2 * GAP;
pBounds.height+= 2 * GAP;
if (eArea.intersects(pBounds)) {
visible= true;
}
}
if (visible && ! fPopup.isVisible()) {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IWidgetTokenOwnerExtension) {
IWidgetTokenOwnerExtension widgetTokenOwnerExtension= (IWidgetTokenOwnerExtension) viewer;
widgetTokenOwnerExtension.requestWidgetToken(this, WIDGET_PRIORITY);
}
} else if (! visible && fPopup.isVisible()) {
releaseWidgetToken();
}
fPopup.setVisible(visible);
}
}
private void releaseWidgetToken() {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IWidgetTokenOwner) {
IWidgetTokenOwner widgetTokenOwner= (IWidgetTokenOwner) viewer;
widgetTokenOwner.releaseWidgetToken(this);
}
}
/**
* @param snapPosition one of the SNAP_POSITION_* constants
* @return the location in display coordinates or <code>null</code> iff not visible
*/
private Point computePopupLocation(int snapPosition) {
if (fPopup == null || fPopup.isDisposed())
return null;
switch (snapPosition) {
case SNAP_POSITION_LOWER_RIGHT:
{
StyledText eWidget= fEditor.getViewer().getTextWidget();
Rectangle eBounds= eWidget.getClientArea();
Point eLowerRight= eWidget.toDisplay(eBounds.x + eBounds.width, eBounds.y + eBounds.height);
Point pSize= getExtent();
return new Point(eLowerRight.x - pSize.x - 5, eLowerRight.y - pSize.y - 5);
}
case SNAP_POSITION_UNDER_RIGHT_FIELD:
case SNAP_POSITION_OVER_RIGHT_FIELD:
{
LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
if (position == null)
return null;
ISourceViewer viewer= fEditor.getViewer();
ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset + position.length);
StyledText textWidget= viewer.getTextWidget();
Point pos= textWidget.getLocationAtOffset(widgetOffset);
Point pSize= getExtent();
if (snapPosition == SNAP_POSITION_OVER_RIGHT_FIELD) {
pos.y-= pSize.y + GAP;
} else {
pos.y+= textWidget.getLineHeight(widgetOffset) + GAP;
}
pos.x+= GAP;
Point dPos= textWidget.toDisplay(pos);
Rectangle displayBounds= textWidget.getDisplay().getClientArea();
Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
Geometry.moveInside(dPopupRect, displayBounds);
return new Point(dPopupRect.x, dPopupRect.y);
}
case SNAP_POSITION_UNDER_LEFT_FIELD:
case SNAP_POSITION_OVER_LEFT_FIELD:
default: // same as SNAP_POSITION_UNDER_LEFT_FIELD
{
LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
if (position == null)
return null;
ISourceViewer viewer= fEditor.getViewer();
ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset/* + position.length*/);
StyledText textWidget= viewer.getTextWidget();
Point pos= textWidget.getLocationAtOffset(widgetOffset);
Point pSize= getExtent();
pSize.y+= HAH + 1;
pos.x-= HAO;
if (snapPosition == SNAP_POSITION_OVER_LEFT_FIELD) {
pos.y-= pSize.y;
} else {
pos.y+= textWidget.getLineHeight(widgetOffset);
}
Point dPos= textWidget.toDisplay(pos);
Rectangle displayBounds= textWidget.getDisplay().getClientArea();
Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
Geometry.moveInside(dPopupRect, displayBounds);
return new Point(dPopupRect.x, dPopupRect.y);
}
}
}
private void addMoveSupport(final Shell popupShell, final Control movedControl) {
movedControl.addMouseListener(new MouseAdapter() {
public void mouseDown(final MouseEvent downEvent) {
if (downEvent.button != 1) {
return;
}
final Point POPUP_SOURCE= popupShell.getLocation();
final StyledText textWidget= fEditor.getViewer().getTextWidget();
Point pSize= getExtent();
int originalSnapPosition= fSnapPosition;
/*
* Feature in Tracker: it is not possible to directly control the feedback,
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121300
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=121298#c1 .
*
* Workaround is to have an offscreen rectangle for tracking mouse movement
* and a manually updated rectangle for the actual drop target.
*/
final Tracker tracker= new Tracker(textWidget, SWT.NONE);
final Point[] LOCATIONS= {
textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_RIGHT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_RIGHT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_LEFT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_LEFT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_LOWER_RIGHT))
};
final Rectangle[] DROP_TARGETS= {
Geometry.createRectangle(LOCATIONS[0], pSize),
Geometry.createRectangle(LOCATIONS[1], pSize),
new Rectangle(LOCATIONS[2].x, LOCATIONS[2].y + HAH, pSize.x, pSize.y),
Geometry.createRectangle(LOCATIONS[3], pSize),
Geometry.createRectangle(LOCATIONS[4], pSize)
};
final Rectangle MOUSE_MOVE_SOURCE= new Rectangle(1000000, 0, 0, 0);
tracker.setRectangles(new Rectangle[] { MOUSE_MOVE_SOURCE, DROP_TARGETS[fSnapPosition] });
tracker.setStippled(true);
ControlListener moveListener= new ControlAdapter() {
/*
* @see org.eclipse.swt.events.ControlAdapter#controlMoved(org.eclipse.swt.events.ControlEvent)
*/
public void controlMoved(ControlEvent moveEvent) {
Rectangle[] currentRects= tracker.getRectangles();
final Rectangle mouseMoveCurrent= currentRects[0];
Point popupLoc= new Point(
POPUP_SOURCE.x + mouseMoveCurrent.x - MOUSE_MOVE_SOURCE.x,
POPUP_SOURCE.y + mouseMoveCurrent.y - MOUSE_MOVE_SOURCE.y);
popupShell.setLocation(popupLoc);
Point ePopupLoc= textWidget.toControl(popupLoc);
int minDist= Integer.MAX_VALUE;
for (int snapPos= 0; snapPos < DROP_TARGETS.length; snapPos++) {
int dist= Geometry.distanceSquared(ePopupLoc, LOCATIONS[snapPos]);
if (dist < minDist) {
minDist= dist;
fSnapPosition= snapPos;
currentRects[1]= DROP_TARGETS[snapPos];
}
}
tracker.setRectangles(currentRects);
}
};
tracker.addControlListener(moveListener);
boolean committed= tracker.open();
tracker.close();
tracker.dispose();
if (committed) {
getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
} else {
fSnapPosition= originalSnapPosition;
}
updatePopupLocation(true);
activateEditor();
}
});
}
private void packPopup() {
boolean isUnderLeft= fSnapPosition == SNAP_POSITION_UNDER_LEFT_FIELD;
boolean isOverLeft= fSnapPosition == SNAP_POSITION_OVER_LEFT_FIELD;
fPopupLayout.marginTop= isUnderLeft ? HAH : 0;
fPopupLayout.marginBottom= isOverLeft ? HAH + 1 : 0;
fPopup.pack();
Region oldRegion= fRegion;
if (isUnderLeft || isOverLeft) {
fRegion= new Region();
fRegion.add(getPolygon(false));
fPopup.setRegion(fRegion);
Rectangle bounds= fRegion.getBounds();
fPopup.setSize(bounds.width, bounds.height + 1);
} else {
fRegion= null;
fPopup.setRegion(null);
}
if (oldRegion != null) {
oldRegion.dispose();
}
}
private Point getExtent() {
Point e = fPopup.getSize();
switch (fSnapPosition) {
case SNAP_POSITION_UNDER_LEFT_FIELD:
e.y -= HAH;
break;
case SNAP_POSITION_OVER_LEFT_FIELD:
e.y -= HAH + 1;
break;
}
return e;
}
private int[] getPolygon(boolean border) {
Point e = getExtent();
int b = border ? 1 : 0;
if (true /*arrowOnLeft*/) {
switch (fSnapPosition) {
case SNAP_POSITION_OVER_LEFT_FIELD:
return new int[] {
0, 0,
e.x - b, 0,
e.x - b, e.y - b,
HAO + HAW, e.y - b,
HAO + HAW / 2, e.y + HAH - b,
HAO, e.y - b,
0, e.y - b,
0, 0 };
case SNAP_POSITION_UNDER_LEFT_FIELD:
return new int[] {
0, HAH,
HAO + b, HAH,
HAO + HAW / 2, b,
HAO + HAW - b, HAH,
e.x - b, HAH,
e.x - b, e.y + HAH - b,
0, e.y + HAH - b,
0, HAH };
default:
return new int[] {
0, 0,
e.x - b, 0,
e.x - b, e.y - b,
0, e.y - b,
0, 0 };
}
}
//TODO: BiDi?
return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b,
e.x - HAO - b, e.y - b, e.x - HAO - HAW / 2, e.y + HAH - b,
e.x - HAO - HAW, e.y - b, 0, e.y - b, 0, 0 };
}
private void createContent(Composite parent) {
Display display= parent.getDisplay();
Color foreground= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
Color background= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
addMoveSupport(fPopup, parent);
StyledText hint= new StyledText(fPopup, SWT.READ_ONLY | SWT.SINGLE);
String enterKeyName= getEnterBinding();
String hintTemplate= ReorgMessages.RenameInformationPopup_EnterNewName;
hint.setText(Messages.format(hintTemplate, enterKeyName));
hint.setForeground(foreground);
hint.setStyleRange(new StyleRange(hintTemplate.indexOf("{0}"), enterKeyName.length(), null, null, SWT.BOLD)); //$NON-NLS-1$
hint.setEnabled(false); // text must not be selectable
addMoveSupport(fPopup, hint);
addViewMenu(parent);
recursiveSetBackgroundColor(parent, background);
}
private ToolBar addViewMenu(final Composite parent) {
fToolBar= new ToolBar(parent, SWT.FLAT);
final ToolItem menuButton = new ToolItem(fToolBar, SWT.PUSH, 0);
fMenuImage= JavaPluginImages.DESC_ELCL_VIEW_MENU.createImage();
menuButton.setImage(fMenuImage);
menuButton.setToolTipText(ReorgMessages.RenameInformationPopup_menu);
fToolBar.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
showMenu(fToolBar);
}
});
menuButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
showMenu(fToolBar);
}
});
fToolBar.pack();
return fToolBar;
}
private void showMenu(ToolBar toolBar) {
Menu menu= getMenuManager().createContextMenu(toolBar);
menu.setLocation(toolBar.toDisplay(0, toolBar.getSize().y));
fIsMenuUp= true;
menu.setVisible(true);
}
private MenuManager getMenuManager() {
if (fMenuManager != null) {
return fMenuManager;
}
fMenuManager= new MenuManager();
fMenuManager.setRemoveAllWhenShown(true);
fMenuManager.addMenuListener(new IMenuListener2() {
public void menuAboutToHide(IMenuManager manager) {
fIsMenuUp= false;
}
public void menuAboutToShow(IMenuManager manager) {
IAction refactorAction= new Action(ReorgMessages.RenameInformationPopup_RenameInWorkspace) {
public void run() {
activateEditor();
fRenameLinkedMode.doRename(false);
}
};
refactorAction.setAccelerator(SWT.CR);
manager.add(refactorAction);
IAction previewAction= new Action(ReorgMessages.RenameInformationPopup_Preview) {
public void run() {
activateEditor();
fRenameLinkedMode.doRename(true);
}
};
previewAction.setAccelerator(SWT.CTRL | SWT.CR);
manager.add(previewAction);
IAction openDialogAction= new Action(ReorgMessages.RenameInformationPopup_OpenDialog + '\t' + fOpenDialogBinding) {
public void run() {
activateEditor();
fRenameLinkedMode.startFullDialog();
}
};
manager.add(openDialogAction);
manager.add(new Separator());
MenuManager subMenuManager= new MenuManager(ReorgMessages.RenameInformationPopup_SnapTo);
addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_LEFT_FIELD, ReorgMessages.RenameInformationPopup_snap_under_left);
addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_RIGHT_FIELD, ReorgMessages.RenameInformationPopup_snap_under_right);
addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_LEFT_FIELD, ReorgMessages.RenameInformationPopup_snap_over_left);
addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_RIGHT_FIELD, ReorgMessages.RenameInformationPopup_snap_over_right);
addMoveMenuItem(subMenuManager, SNAP_POSITION_LOWER_RIGHT, ReorgMessages.RenameInformationPopup_snap_bottom_right);
manager.add(subMenuManager);
IAction prefsAction= new Action(ReorgMessages.RenameInformationPopup_preferences) {
public void run() {
fRenameLinkedMode.cancel();
String linkedModePrefPageID= "org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage"; //$NON-NLS-1$
String refactoringPrefPageID= JavaBasePreferencePage.JAVA_BASE_PREF_PAGE_ID;
PreferencesUtil.createPreferenceDialogOn(fEditor.getSite().getShell(), refactoringPrefPageID, new String[] { linkedModePrefPageID, refactoringPrefPageID }, null).open();
}
};
manager.add(prefsAction);
}
});
return fMenuManager;
}
private void addMoveMenuItem(IMenuManager manager, final int snapPosition, String text) {
IAction action= new Action(text, IAction.AS_RADIO_BUTTON) {
public void run() {
fSnapPosition= snapPosition;
getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
updatePopupLocation(true);
activateEditor();
}
};
action.setChecked(fSnapPosition == snapPosition);
manager.add(action);
}
private static String getEnterBinding() {
return KeyStroke.getInstance(KeyLookupFactory.getDefault().formalKeyLookup(IKeyLookup.CR_NAME)).format();
}
/**
* WARNING: only works in workbench window context!
* @return the keybinding for Refactor &gt; Rename
*/
private static String getOpenDialogBinding() {
IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
if (bindingService == null)
return ""; //$NON-NLS-1$
String binding= bindingService.getBestActiveBindingFormattedFor(IJavaEditorActionDefinitionIds.RENAME_ELEMENT);
return binding == null ? "" : binding; //$NON-NLS-1$
}
private static void recursiveSetBackgroundColor(Control control, Color color) {
control.setBackground(color);
if (control instanceof Composite) {
Control[] children= ((Composite) control).getChildren();
for (int i= 0; i < children.length; i++) {
recursiveSetBackgroundColor(children[i], color);
}
}
}
public boolean ownsFocusShell() {
if (fIsMenuUp)
return true;
if (fPopup == null || fPopup.isDisposed())
return false;
Shell activeShell= fPopup.getDisplay().getActiveShell();
if (fPopup == activeShell)
return true;
return false;
}
private void activateEditor() {
fEditor.getSite().getShell().setActive();
}
public boolean requestWidgetToken(IWidgetTokenOwner owner) {
return false;
}
public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
return false;
}
public boolean setFocus(IWidgetTokenOwner owner) {
if (fToolBar != null && ! fToolBar.isDisposed())
showMenu(fToolBar);
return true;
}
}