Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(835)

Unified Diff: editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/refactoring/reorg/RenameInformationPopup.java

Issue 9834028: Initial implementation of "Rename Local Variable" refactoring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: LInked/inline mode for rename Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/refactoring/reorg/RenameInformationPopup.java
diff --git a/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/refactoring/reorg/RenameInformationPopup.java b/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/refactoring/reorg/RenameInformationPopup.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3c2e912e2f6846d87657dc192b84780fc1a9b99
--- /dev/null
+++ b/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/refactoring/reorg/RenameInformationPopup.java
@@ -0,0 +1,871 @@
+package com.google.dart.tools.ui.internal.refactoring.reorg;
+
+import com.google.dart.tools.internal.corext.refactoring.util.Messages;
+import com.google.dart.tools.ui.DartPluginImages;
+import com.google.dart.tools.ui.DartToolsPlugin;
+import com.google.dart.tools.ui.actions.DartEditorActionDefinitionIds;
+import com.google.dart.tools.ui.internal.text.editor.CompilationUnitEditor;
+
+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.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.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.jface.util.Geometry;
+import org.eclipse.jface.util.Util;
+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.ui.IPartListener2;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.progress.UIJob;
+
+public class RenameInformationPopup implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
+
+ private class PopupVisibilityManager implements IPartListener2, ControlListener, MouseListener,
+ KeyListener, ITextListener, IViewportListener {
+
+ @Override
+ public void controlMoved(ControlEvent e) {
+ updatePopupLocation(true);
+ updateVisibility(); //only for hiding outside editor area
+ }
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ updatePopupLocation(true);
+ updateVisibility(); //only for hiding outside editor area
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ updatePopupLocation(false);
+ updateVisibility();
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseDown(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseUp(MouseEvent e) {
+ updatePopupLocation(false);
+ updateVisibility();
+ }
+
+ @Override
+ public void partActivated(IWorkbenchPartReference partRef) {
+ IWorkbenchPart fPart = fEditor.getEditorSite().getPart();
+ if (partRef.getPart(false) == fPart) {
+ updateVisibility();
+ }
+ }
+
+ @Override
+ public void partBroughtToTop(IWorkbenchPartReference partRef) {
+ }
+
+ @Override
+ public void partClosed(IWorkbenchPartReference partRef) {
+ }
+
+ @Override
+ public void partDeactivated(IWorkbenchPartReference partRef) {
+ IWorkbenchPart fPart = fEditor.getEditorSite().getPart();
+ if (fPopup != null && !fPopup.isDisposed() && partRef.getPart(false) == fPart) {
+ fPopup.setVisible(false);
+ }
+ }
+
+ @Override
+ public void partHidden(IWorkbenchPartReference partRef) {
+ }
+
+ @Override
+ public void partInputChanged(IWorkbenchPartReference partRef) {
+ }
+
+ @Override
+ public void partOpened(IWorkbenchPartReference partRef) {
+ }
+
+ @Override
+ public void partVisible(IWorkbenchPartReference partRef) {
+ }
+
+ 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() {
+ @Override
+ 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();
+ }
+ });
+ }
+
+ @Override
+ public void textChanged(TextEvent event) {
+ if (!event.getViewerRedrawState()) {
+ return;
+ }
+ updatePopupLocation(false);
+ updateVisibility(); //only for hiding outside editor area
+ }
+
+ @Override
+ public void viewportChanged(int verticalOffset) {
+ updatePopupLocation(true);
+ updateVisibility(); //only for hiding outside editor area
+ }
+ }
+
+ /**
+ * Cached platform flag for dealing with platform-specific issue:
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=219326 : Shell with custom region and SWT.NO_TRIM
+ * still has border
+ */
+ private static boolean MAC = Util.isMac();
+
+ 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 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 > Rename
+ */
+ private static String getOpenDialogBinding() {
+ IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(
+ IBindingService.class);
+ if (bindingService == null) {
+ return ""; //$NON-NLS-1$
+ }
+ String binding = bindingService.getBestActiveBindingFormattedFor(DartEditorActionDefinitionIds.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);
+ }
+ }
+ }
+
+ private final CompilationUnitEditor fEditor;
+ private final RenameLinkedMode fRenameLinkedMode;
+ private int fSnapPosition;
+ private boolean fSnapPositionChanged;
+
+ 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();
+ }
+
+ 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;
+ }
+
+ 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() {
+ @Override
+ 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
+ @Override
+ public void run() {
+ Shell activeShell = display.getActiveShell();
+ if (activeShell != editorShell) {
+ fRenameLinkedMode.cancel();
+ }
+ }
+ });
+ }
+ });
+
+ if (!MAC) { // carbon and cocoa draw their own border...
+ fPopup.addPaintListener(new PaintListener() {
+ @Override
+ 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) {
+ @Override
+ 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 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;
+ }
+
+ @Override
+ public boolean requestWidgetToken(IWidgetTokenOwner owner) {
+ return false;
+ }
+
+ @Override
+ public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
+ return false;
+ }
+
+ @Override
+ public boolean setFocus(IWidgetTokenOwner owner) {
+ if (fToolBar != null && !fToolBar.isDisposed()) {
+ showMenu(fToolBar);
+ }
+ return true;
+ }
+
+ private void activateEditor() {
+ fEditor.getSite().getShell().setActive();
+ }
+
+ private void addMoveMenuItem(IMenuManager manager, final int snapPosition, String text) {
+ IAction action = new Action(text, IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ fSnapPosition = snapPosition;
+ fSnapPositionChanged = true;
+ getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
+ updatePopupLocation(true);
+ activateEditor();
+ }
+ };
+ action.setChecked(fSnapPosition == snapPosition);
+ manager.add(action);
+ }
+
+ private void addMoveSupport(final Shell popupShell, final Control movedControl) {
+ movedControl.addMouseListener(new MouseAdapter() {
+
+ @Override
+ 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)
+ */
+ @Override
+ 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;
+ fSnapPositionChanged = true;
+ 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;
+ fSnapPositionChanged = true;
+ }
+ updatePopupLocation(true);
+ activateEditor();
+ }
+ });
+ }
+
+ private ToolBar addViewMenu(final Composite parent) {
+ fToolBar = new ToolBar(parent, SWT.FLAT);
+ final ToolItem menuButton = new ToolItem(fToolBar, SWT.PUSH, 0);
+ fMenuImage = DartPluginImages.DESC_ELCL_VIEW_MENU.createImage();
+ menuButton.setImage(fMenuImage);
+ menuButton.setToolTipText(ReorgMessages.RenameInformationPopup_menu);
+ fToolBar.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ showMenu(fToolBar);
+ }
+ });
+ menuButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ showMenu(fToolBar);
+ }
+ });
+ fToolBar.pack();
+ return fToolBar;
+ }
+
+ /**
+ * @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 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 IDialogSettings getDialogSettings() {
+ return DartToolsPlugin.getDefault().getDialogSettingsSection(DIALOG_SETTINGS_SECTION);
+ }
+
+ 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 MenuManager getMenuManager() {
+ if (fMenuManager != null) {
+ return fMenuManager;
+ }
+
+ fMenuManager = new MenuManager();
+ fMenuManager.setRemoveAllWhenShown(true);
+
+ fMenuManager.addMenuListener(new IMenuListener2() {
+ @Override
+ public void menuAboutToHide(IMenuManager manager) {
+ fIsMenuUp = false;
+ }
+
+ @Override
+ public void menuAboutToShow(IMenuManager manager) {
+ boolean canRefactor = !fRenameLinkedMode.isOriginalName();
+
+ IAction refactorAction = new Action(ReorgMessages.RenameInformationPopup_RenameInWorkspace) {
+ @Override
+ public void run() {
+ activateEditor();
+ fRenameLinkedMode.doRename(false);
+ }
+ };
+ refactorAction.setAccelerator(SWT.CR);
+ refactorAction.setEnabled(canRefactor);
+ manager.add(refactorAction);
+
+ IAction previewAction = new Action(ReorgMessages.RenameInformationPopup_Preview) {
+ @Override
+ public void run() {
+ activateEditor();
+ fRenameLinkedMode.doRename(true);
+ }
+ };
+ previewAction.setAccelerator(SWT.CTRL | SWT.CR);
+ previewAction.setEnabled(canRefactor);
+ manager.add(previewAction);
+
+ IAction openDialogAction = new Action(ReorgMessages.RenameInformationPopup_OpenDialog
+ + '\t' + fOpenDialogBinding) {
+ @Override
+ 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) {
+// @Override
+// 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 int[] getPolygon(boolean border) {
+ Point e = getExtent();
+ int b = border ? 1 : 0;
+ boolean isRTL = (fPopup.getStyle() & SWT.RIGHT_TO_LEFT) != 0;
+ int ha1 = isRTL ? e.x - HAO : HAO + HAW;
+ int ha2 = isRTL ? e.x - HAO - HAW / 2 : HAO + HAW / 2;
+ int ha3 = isRTL ? e.x - HAO - HAW : HAO;
+ int[] poly;
+ switch (fSnapPosition) {
+ case SNAP_POSITION_OVER_LEFT_FIELD:
+ poly = new int[] {
+ 0, 0, e.x - b, 0, e.x - b, e.y - b, ha1, e.y - b, ha2, e.y + HAH - b, ha3, e.y - b, 0,
+ e.y - b, 0, 0};
+ break;
+
+ case SNAP_POSITION_UNDER_LEFT_FIELD:
+ poly = new int[] {
+ 0, HAH, ha3 + b, HAH, ha2, b, ha1 - b, HAH, e.x - b, HAH, e.x - b, e.y + HAH - b, 0,
+ e.y + HAH - b, 0, HAH};
+ break;
+
+ default:
+ poly = new int[] {0, 0, e.x - b, 0, e.x - b, e.y - b, 0, e.y - b, 0, 0};
+ break;
+ }
+ return poly;
+ }
+
+ private void packPopup() {
+ if (!fSnapPositionChanged) {
+ return;
+ }
+ fSnapPositionChanged = false;
+
+ 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 void releaseWidgetToken() {
+ ISourceViewer viewer = fEditor.getViewer();
+ if (viewer instanceof IWidgetTokenOwner) {
+ IWidgetTokenOwner widgetTokenOwner = (IWidgetTokenOwner) viewer;
+ widgetTokenOwner.releaseWidgetToken(this);
+ }
+ }
+
+ private void restoreSnapPosition() {
+ IDialogSettings settings = getDialogSettings();
+ try {
+ fSnapPosition = settings.getInt(SNAP_POSITION_KEY);
+ } catch (NumberFormatException e) {
+ // default:
+ fSnapPosition = SNAP_POSITION_UNDER_LEFT_FIELD;
+ }
+ fSnapPositionChanged = true;
+ }
+
+ private void showMenu(ToolBar toolBar) {
+ Menu menu = getMenuManager().createContextMenu(toolBar);
+ menu.setLocation(toolBar.toDisplay(0, toolBar.getSize().y));
+ fIsMenuUp = true;
+ menu.setVisible(true);
+ }
+
+ private void updatePopupLocation(boolean force) {
+ if (!force && fSnapPosition == SNAP_POSITION_LOWER_RIGHT) {
+ return;
+ }
+
+ packPopup();
+ Point loc = computePopupLocation(fSnapPosition);
+ if (loc != null && !loc.equals(fPopup.getLocation())) {
+ 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);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698