/*******************************************************************************
 * 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;
	}
}
