Bug 92901 - Popup control should be installed once on each control
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
index 1a0a3b5..7b703ea 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
@@ -174,4 +174,6 @@
 	public static String OpenTypeAction_0;
 
 	public static String OpenTypeAction_1;
+
+    public static String PopupDisplayAction_1;
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
index c85c11f..3645814 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
@@ -124,6 +124,7 @@
 BreakpointLocationVerifierJob_breakpointMovedToValidPosition=The breakpoint has been moved to a valid position.
 BreakpointLocationVerifierJob_breakpointSetToRightType=The breakpoint has been set to the right type.
 PopupDisplayAction_2=Move to Display View
+PopupDisplayAction_1=Press {0} to {1}
 
 RunToLineAdapter_0=Empty editor
 RunToLineAdapter_1=Missing document
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupDisplayAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupDisplayAction.java
index a1bdd8c..5500098 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupDisplayAction.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupDisplayAction.java
@@ -10,185 +10,120 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.actions;
 
+import java.text.MessageFormat;
 
-import org.eclipse.debug.internal.ui.views.expression.PopupInformationControl;
+import org.eclipse.debug.ui.DebugPopup;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
 import org.eclipse.jdt.internal.debug.ui.display.DisplayView;
 import org.eclipse.jdt.internal.debug.ui.display.IDataDisplay;
 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
-import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IInformationControl;
-import org.eclipse.jface.text.IInformationControlCreator;
-import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.bindings.TriggerSequence;
 import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.information.IInformationProvider;
-import org.eclipse.jface.text.information.InformationPresenter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.keys.IBindingService;
 
+public class PopupDisplayAction extends DisplayAction {
 
-public class PopupDisplayAction extends DisplayAction implements IInformationProvider {
-	
-	public static final String ACTION_DEFINITION_ID = "org.eclipse.jdt.debug.ui.commands.Display"; //$NON-NLS-1$
-	
-	private ITextViewer viewer;
-	private String snippet;
-	private String resultString;
+    public static final String ACTION_DEFINITION_ID = "org.eclipse.jdt.debug.ui.commands.Display"; //$NON-NLS-1$
 
-    private InformationPresenter fInformationPresenter;
+    private ITextViewer viewer;
 
-	public PopupDisplayAction() {
-		super();
-	}
-	
-	public String getInformation(ITextViewer textViewer, IRegion subject) {
-		return resultString;
-	}
+    private String snippet;
 
-	public IRegion getSubject(ITextViewer textViewer, int offset) {
-		return getRegion();
-	}
-	
-	private InformationPresenter getInformationPresenter() {
-	    return fInformationPresenter;
+    private String resultString;
+
+    public PopupDisplayAction() {
+        super();
     }
-	private void setInformationPresenter(InformationPresenter informationPresenter) {
-	    fInformationPresenter = informationPresenter;
+
+    private void showPopup() {
+        DebugPopup displayPopup = new DisplayPopup(getShell(), viewer);
+        displayPopup.open();
     }
-	
-	private void showPopup() {		
-        if (viewer != null) {
-            final InformationPresenter infoPresenter = new InformationPresenter(new IInformationControlCreator() {
-                public IInformationControl createInformationControl(Shell parent) {
-                    DisplayInformationControl control = new DisplayInformationControl(parent, ActionMessages.PopupDisplayAction_2, ACTION_DEFINITION_ID); 
-                    control.addDisposeListener(new DisposeListener() {
-                        public void widgetDisposed(DisposeEvent e) {
-                            getInformationPresenter().uninstall();
-                        }
-                    });
-                    return control; 
+
+    private class DisplayPopup extends DebugPopup {
+        public DisplayPopup(Shell shell, ITextViewer viewer) {
+            super(shell, viewer);
+        }
+
+        protected String getInfoText() {
+            IWorkbench workbench = PlatformUI.getWorkbench();
+            IBindingService bindingService = (IBindingService) workbench.getAdapter(IBindingService.class);
+            TriggerSequence[] bindings = bindingService.getActiveBindingsFor(ACTION_DEFINITION_ID);
+            if (bindings.length > 0) {
+                String infoText = MessageFormat.format(ActionMessages.PopupDisplayAction_1, new String[] { bindings[0].format(), ActionMessages.PopupDisplayAction_2 });
+                setInfoText(infoText);
+            }
+            return null;
+        }
+
+        protected String getCommandId() {
+            return ACTION_DEFINITION_ID;
+        }
+
+        protected void persist() {
+            IDataDisplay directDisplay = getDirectDataDisplay();
+            Display display = JDIDebugUIPlugin.getStandardDisplay();
+
+            if (!display.isDisposed()) {
+                IDataDisplay dataDisplay = getDataDisplay();
+                if (dataDisplay != null) {
+                    if (directDisplay == null) {
+                        dataDisplay.displayExpression(snippet);
+                    }
+                    dataDisplay.displayExpressionValue(resultString);
                 }
-            });
-
-            setInformationPresenter(infoPresenter);
-
-            Point p = viewer.getSelectedRange();
-            IDocument doc = viewer.getDocument();
-            try {
-                String contentType = doc.getContentType(p.x);
-                infoPresenter.setInformationProvider(PopupDisplayAction.this, contentType);
-
-                infoPresenter.install(viewer);
-                infoPresenter.showInformation();
-            } catch (BadLocationException e) {
-                return;
-            } finally {
-                viewer = null;
             }
         }
-	}
 
-    private class DisplayInformationControl extends PopupInformationControl {
-		private StyledText text;
-		
-		DisplayInformationControl(Shell shell, String label, String actionDefinitionId) {
-			super(shell, label, actionDefinitionId);
-		}
-				
-		public Control createControl(Composite parent) {
-			GridData gd = new GridData(GridData.FILL_BOTH);
-			text = new StyledText(parent, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL );
-			text.setLayoutData(gd);
-			
-			text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
-			text.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
-			return text;
-		}
+        protected Control createDialogArea(Composite parent) {
+            GridData gd = new GridData(GridData.FILL_BOTH);
+            StyledText text = new StyledText(parent, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL);
+            text.setLayoutData(gd);
 
-		protected IDialogSettings getDialogSettings() {
-			return JDIDebugUIPlugin.getDefault().getDialogSettings();
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.debug.ui.actions.PopupInformationControl#performCommand()
-		 */
-		protected void performCommand() {
-			IDataDisplay directDisplay= getDirectDataDisplay();
-			Display display= JDIDebugUIPlugin.getStandardDisplay();
-			
-			if (!display.isDisposed()) {
-				IDataDisplay dataDisplay= getDataDisplay();
-				if (dataDisplay != null) {
-					if (directDisplay == null) {
-						dataDisplay.displayExpression(snippet);
-					}
-					dataDisplay.displayExpressionValue(resultString);
-				}
-			}
-		}
+            text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+            text.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
-		 */
-		public boolean hasContents() {
-			return (text != null && text.getCharCount() >0);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
-		 */
-		public void setInformation(String information) {
-			if(information != null) {
-				text.setFont(viewer.getTextWidget().getFont());
-				text.setText(DisplayAction.trimDisplayResult(information));
-			}
-		}
-
-	}
-
-	protected void displayStringResult(String currentSnippet, String currentResultString) {
-		IWorkbenchPart part = getTargetPart();
-		
-		if (part instanceof DisplayView) {
-			super.displayStringResult(currentSnippet, currentResultString);
-			return;
-		}
-		viewer = (ITextViewer) part.getAdapter(ITextViewer.class);
-		if (viewer == null) {
-			if (part instanceof JavaEditor) {
-				viewer = ((JavaEditor)part).getViewer();
-			}
-		}
-		if (viewer == null) {
-			super.displayStringResult(currentSnippet, currentResultString);
-		} else {
-			snippet = currentSnippet;
-			resultString = currentResultString;
-			Display.getDefault().asyncExec(new Runnable() {
-				public void run() {
-					showPopup();
-				}
-			});
-            evaluationCleanup();
-		}
-	}
-
-    protected IRegion getRegion() {
-        Point point = viewer.getSelectedRange();
-        return new Region(point.x, point.y);
+            text.setText(resultString);
+            return text;
+        }
     }
 
+    protected void displayStringResult(String currentSnippet, String currentResultString) {
+        IWorkbenchPart part = getTargetPart();
+
+        if (part instanceof DisplayView) {
+            super.displayStringResult(currentSnippet, currentResultString);
+            return;
+        }
+        
+        viewer = (ITextViewer) part.getAdapter(ITextViewer.class);
+        if (viewer == null) {
+            if (part instanceof JavaEditor) {
+                viewer = ((JavaEditor)part).getViewer();
+            }
+        }
+        if (viewer == null) {
+            super.displayStringResult(currentSnippet, currentResultString);
+        } else {
+            snippet = currentSnippet;
+            resultString = currentResultString;
+            Display.getDefault().asyncExec(new Runnable() {
+                public void run() {
+                    showPopup();
+                }
+            });
+            evaluationCleanup();
+        }
+    }
 
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupInspectAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupInspectAction.java
index c509607..c07184b 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupInspectAction.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/PopupInspectAction.java
@@ -10,117 +10,52 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.actions;
 
-
-import org.eclipse.debug.internal.ui.views.expression.ExpressionInformationControl;
+import org.eclipse.debug.ui.DebugPopup;
+import org.eclipse.debug.ui.InspectPopupDialog;
 import org.eclipse.jdt.debug.eval.IEvaluationResult;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
 import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression;
 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IInformationControl;
-import org.eclipse.jface.text.IInformationControlCreator;
-import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.TextUtilities;
-import org.eclipse.jface.text.information.IInformationProvider;
-import org.eclipse.jface.text.information.InformationPresenter;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.IWorkbenchPart;
 
+public class PopupInspectAction extends InspectAction {
 
-public class PopupInspectAction extends InspectAction implements IInformationProvider {
-	
-	public static final String ACTION_DEFININIITION_ID = "org.eclipse.jdt.debug.ui.commands.Inspect"; //$NON-NLS-1$
-	
-	private ITextViewer viewer;
-	private JavaInspectExpression expression;
+    public static final String ACTION_DEFININIITION_ID = "org.eclipse.jdt.debug.ui.commands.Inspect"; //$NON-NLS-1$
 
-    private InformationPresenter fInformationPresenter;
-	
-	/**
-	 * @see EvaluateAction#displayResult(IEvaluationResult)
-	 */
-	protected void displayResult(final IEvaluationResult result) {
-		IWorkbenchPart part = getTargetPart();
-		viewer = (ITextViewer) part.getAdapter(ITextViewer.class);
-		if (viewer == null) {
-			if (part instanceof JavaEditor) {
-				viewer = ((JavaEditor)part).getViewer();
-			}
-		}
-		if (viewer == null) {
-			super.displayResult(result);
-		} else {
-			showPopup(result);
-		}		
-		
-		evaluationCleanup();
-	}
-	
-	private InformationPresenter getInformationPresenter() {
-	    return fInformationPresenter;
-    }
-	
-	private void setInformationPresenter(InformationPresenter informationPresenter) {
-	    fInformationPresenter = informationPresenter;
-	}
-	
-	protected void showPopup(final IEvaluationResult result) {
-		final InformationPresenter infoPresenter = new InformationPresenter(new IInformationControlCreator() {
-			public IInformationControl createInformationControl(Shell parent) {
-				IWorkbenchPage page = JDIDebugUIPlugin.getActivePage();
-				expression = new JavaInspectExpression(result);
-				ExpressionInformationControl control = new ExpressionInformationControl(page, expression, ACTION_DEFININIITION_ID);
-				control.addDisposeListener(new DisposeListener() {
-                    public void widgetDisposed(DisposeEvent e) {
-                        getInformationPresenter().uninstall();
-                    }
-				});
-				return control;
-			}
-		});
-		
-		setInformationPresenter(infoPresenter);
+    private ITextViewer viewer;
 
-		JDIDebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
-			public void run() {
-                if (viewer != null) {
-                    Point p = viewer.getSelectedRange();
-                    IDocument doc = viewer.getDocument();
-                    try {
-                        String contentType = TextUtilities.getContentType(doc, infoPresenter.getDocumentPartitioning(), p.x, true);
-                        infoPresenter.setInformationProvider(PopupInspectAction.this, contentType);
-                        infoPresenter.install(viewer);
-                        infoPresenter.showInformation();
-                    } catch (BadLocationException e) {
-                        return;
-                    } finally {
-                        viewer = null;
-                    }
-                }
+    JavaInspectExpression expression;
+
+    /**
+     * @see EvaluateAction#displayResult(IEvaluationResult)
+     */
+    protected void displayResult(final IEvaluationResult result) {
+        expression = new JavaInspectExpression(result);
+        
+        IWorkbenchPart part = getTargetPart();
+        viewer = (ITextViewer) part.getAdapter(ITextViewer.class);
+        if (viewer == null) {
+            if (part instanceof JavaEditor) {
+                viewer = ((JavaEditor) part).getViewer();
             }
-		});
-	}
-	
-	public IRegion getSubject(ITextViewer textViewer, int offset) {
-		return getRegion();
-	}
-	
-	public String getInformation(ITextViewer textViewer, IRegion subject) {
-//		the ExpressionInformationControlAdapter was constructed with everything that it needs
-//		returning null would result in popup not being displayed 
-		return "not null";  //$NON-NLS-1$
-	}
-	
-    protected IRegion getRegion() {
-        Point point = viewer.getSelectedRange();
-        return new Region(point.x, point.y);
-    }	
+        }
+        if (viewer == null) {
+            super.displayResult(result);
+        } else {
+            JDIDebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
+                public void run() {
+                    showPopup();
+                }
+            });
+        }
+
+        evaluationCleanup();
+    }
+
+    protected void showPopup() {
+        DebugPopup displayPopup = new InspectPopupDialog(getShell(), viewer, ACTION_DEFININIITION_ID, expression);
+        displayPopup.open();
+    }
 
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/snippeteditor/JavaSnippetEditor.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/snippeteditor/JavaSnippetEditor.java
index d5cc78b..1ac5437 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/snippeteditor/JavaSnippetEditor.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/snippeteditor/JavaSnippetEditor.java
@@ -40,11 +40,11 @@
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
 import org.eclipse.debug.core.model.IValue;
-import org.eclipse.debug.internal.ui.views.expression.ExpressionInformationControl;
 import org.eclipse.debug.ui.DebugUITools;
 import org.eclipse.debug.ui.IDebugModelPresentation;
 import org.eclipse.debug.ui.IDebugUIConstants;
 import org.eclipse.debug.ui.IValueDetailListener;
+import org.eclipse.debug.ui.InspectPopupDialog;
 import org.eclipse.jdt.core.CompletionRequestor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
@@ -87,24 +87,15 @@
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IInformationControl;
-import org.eclipse.jface.text.IInformationControlCreator;
-import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.ITextSelection;
-import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.TextUtilities;
 import org.eclipse.jface.text.contentassist.ContentAssistant;
 import org.eclipse.jface.text.contentassist.IContentAssistant;
-import org.eclipse.jface.text.information.IInformationProvider;
 import org.eclipse.jface.text.information.InformationPresenter;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.jface.text.source.IVerticalRuler;
 import org.eclipse.jface.text.source.SourceViewerConfiguration;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.swt.custom.BusyIndicator;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
@@ -803,44 +794,12 @@
 	}
 	
 	private void showExpression(final JavaInspectExpression expression) {
-		Runnable r = new Runnable() {
-			public void run() {
-			    fInfoPresenter = new InformationPresenter(new IInformationControlCreator() {
-			        public IInformationControl createInformationControl(Shell parent) {
-			            IWorkbenchPage page = JDIDebugUIPlugin.getActivePage();
-			            ExpressionInformationControl control = new ExpressionInformationControl(page, expression, PopupInspectAction.ACTION_DEFININIITION_ID);
-                        control.addDisposeListener(new DisposeListener() {
-                            public void widgetDisposed(DisposeEvent e) {
-                                fInfoPresenter.uninstall();
-                                fInfoPresenter = null;
-                            }
-                        });
-			            return control;
-			        }
-			    });
-
-				IInformationProvider provider = new IInformationProvider() {
-					public IRegion getSubject(ITextViewer textViewer, int offset) {
-						return new Region(fSnippetStart, fSnippetEnd-fSnippetStart);
-					}
-					public String getInformation(ITextViewer textViewer, IRegion subject) {
-						return "nothing"; //$NON-NLS-1$
-					}
-					
-				};
-
-				try {
-				    String contentType = TextUtilities.getContentType(getSourceViewer().getDocument(), fInfoPresenter.getDocumentPartitioning(), fSnippetStart, true);
-				    fInfoPresenter.setInformationProvider(provider, contentType);
-				    fInfoPresenter.install(getSourceViewer());
-				    fInfoPresenter.showInformation();
-				} catch (BadLocationException e) {
-					return;
-				}
-				
-			}
-		};
-		async(r);
+	    Runnable r = new Runnable() {
+	        public void run() {
+	            new InspectPopupDialog(getShell(), getSourceViewer(), PopupInspectAction.ACTION_DEFININIITION_ID, expression).open();
+	        }
+	    };
+	    async(r);
 	}