1.什么是JDT的hover。
见下图:
2. hover中的不同的字体,和颜色是如何显示出来的。
其实在对应的hover中,返回的是String类型,内容是html,然后通过org.eclipse.swt.browser.Browser显示出来的。
3.工作原理:
3.1 add MouseTracker to current SourceViewer, when you open java file.
org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer
-->
org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer
/**
* After this method has been executed the caller knows that any installed text hover has been installed.
*/
private void ensureHoverControlManagerInstalled() {
if (fTextHovers != null && !fTextHovers.isEmpty() && fHoverControlCreator != null && fTextHoverManager == null) {
fTextHoverManager= new TextViewerHoverManager(this, fHoverControlCreator);
fTextHoverManager.install(this.getTextWidget());
fTextHoverManager.setSizeConstraints(TEXT_HOVER_WIDTH_CHARS, TEXT_HOVER_HEIGHT_CHARS, false, true);
fTextHoverManager.setInformationControlReplacer(new StickyHoverManager(this));
}
}
--> org.eclipse.jface.text.TextViewerHoverManager
public void install(Control subjectControl) {
if (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControlDisposeListener != null)
fSubjectControl.removeDisposeListener(fSubjectControlDisposeListener);
fSubjectControl= subjectControl;
if (fSubjectControl != null)
fSubjectControl.addDisposeListener(getSubjectControlDisposeListener());
if (fInformationControlCloser != null)
fInformationControlCloser.setSubjectControl(subjectControl);
setEnabled(true);
fDisposed= false;
}
--> org.eclipse.jface.text.TextViewerHoverManager
public void setEnabled(boolean enabled) {
boolean was= isEnabled();
super.setEnabled(enabled);
boolean is= isEnabled();
if (was != is && fMouseTracker != null) {
if (is)
fMouseTracker.start(getSubjectControl());
else
fMouseTracker.stop();
}
}
-->
org.eclipse.jface.text.AbstractHoverInformationControlManager$MouseTracker
public void start(Control subjectControl) {
fSubjectControl= subjectControl;
if (fSubjectControl != null && !fSubjectControl.isDisposed())
fSubjectControl.addMouseTrackListener(this);
fIsInRestartMode= false;
fIsComputing= false;
fMouseLostWhileComputing= false;
fShellDeactivatedWhileComputing= false;
}
3.2 when you hover mouse on target SourceViewer, it will show hover
org.eclipse.jface.text.AbstractHoverInformationControlManager$MouseTracker
public void mouseHover(MouseEvent event) {
if (fIsComputing || fIsInRestartMode ||
(fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControl.getShell() != fSubjectControl.getShell().getDisplay().getActiveShell())) {
if (DEBUG)
System.out.println("AbstractHoverInformationControlManager...mouseHover: @ " + event.x + "/" + event.y + " : hover cancelled: fIsComputing= " + fIsComputing + ", fIsInRestartMode= " + fIsInRestartMode); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
return;
}
fIsInRestartMode= true;
fIsComputing= true;
fMouseLostWhileComputing= false;
fShellDeactivatedWhileComputing= false;
fHoverEventStateMask= event.stateMask;
fHoverEvent= event;
fHoverArea= new Rectangle(event.x - EPSILON, event.y - EPSILON, 2 * EPSILON, 2 * EPSILON );
if (fHoverArea.x < 0)
fHoverArea.x= 0;
if (fHoverArea.y < 0)
fHoverArea.y= 0;
setSubjectArea(fHoverArea);
if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
fSubjectControl.addMouseMoveListener(this);
fSubjectControl.getShell().addShellListener(this);
}
doShowInformation();
}
--> org.eclipse.jface.text.AbstractInformationControlManager
protected void doShowInformation() {
fSubjectArea= null;
fInformation= null;
computeInformation();
}
--> org.eclipse.jface.text.TextViewerHoverManager
protected void computeInformation() {
//create a thread(Text Viewer Hover Presenter) to show hover
}
…
-->
org.eclipse.jface.text.AbstractInformationControlManager.internalShowInformationControl(Rectangle,
Object) to create control to show the text.
private void internalShowInformationControl(Rectangle subjectArea, Object information) {
if (this instanceof InformationControlReplacer) {
((InformationControlReplacer) this).showInformationControl(subjectArea, information);
return;
}
IInformationControl informationControl= getInformationControl();
if (informationControl != null) {
Point sizeConstraints= computeSizeConstraints(fSubjectControl, fSubjectArea, informationControl);
if (informationControl instanceof IInformationControlExtension3) {
IInformationControlExtension3 iControl3= (IInformationControlExtension3) informationControl;
Rectangle trim= iControl3.computeTrim();
sizeConstraints.x += trim.width;
sizeConstraints.y += trim.height;
}
informationControl.setSizeConstraints(sizeConstraints.x, sizeConstraints.y);
if (informationControl instanceof IInformationControlExtension2)
((IInformationControlExtension2)informationControl).setInput(information);
else
informationControl.setInformation(information.toString());
if (informationControl instanceof IInformationControlExtension) {
IInformationControlExtension extension= (IInformationControlExtension)informationControl;
if (!extension.hasContents())
return;
}
Point size= null;
Point location= null;
Rectangle bounds= restoreInformationControlBounds();
if (bounds != null) {
if (bounds.x > -1 && bounds.y > -1)
location= Geometry.getLocation(bounds);
if (bounds.width > -1 && bounds.height > -1)
size= Geometry.getSize(bounds);
}
if (size == null)
size= informationControl.computeSizeHint();
if (fEnforceAsMinimalSize)
size= Geometry.max(size, sizeConstraints);
if (fEnforceAsMaximalSize)
size= Geometry.min(size, sizeConstraints);
if (location == null)
location= computeInformationControlLocation(subjectArea, size);
Rectangle controlBounds= Geometry.createRectangle(location, size);
cropToClosestMonitor(controlBounds);
location= Geometry.getLocation(controlBounds);
size= Geometry.getSize(controlBounds);
informationControl.setLocation(location);
informationControl.setSize(size.x, size.y);
showInformationControl(subjectArea);
}
}
--> org.eclipse.jface.text.AbstractInformationControlManager
protected void showInformationControl(Rectangle subjectArea) {
fInformationControl.setVisible(true);
if (fInformationControl == null)
return; // could already be disposed if setVisible(..) runs the display loop
if (fTakesFocusWhenVisible)
fInformationControl.setFocus();
if (fInformationControlCloser != null)
fInformationControlCloser.start(subjectArea);
}
org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover$HoverControlCreator
public IInformationControl doCreateInformationControl(Shell parent) {
String tooltipAffordanceString= fAdditionalInfoAffordance ? JavaPlugin.getAdditionalInfoAffordanceString() : EditorsUI.getTooltipAffordanceString();
if (BrowserInformationControl.isAvailable(parent)) {
String font= PreferenceConstants.APPEARANCE_JAVADOC_FONT;
BrowserInformationControl iControl= new BrowserInformationControl(parent, font, tooltipAffordanceString) {
/*
* @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator()
*/
@Override
public IInformationControlCreator getInformationPresenterControlCreator() {
return fInformationPresenterControlCreator;
}
};
addLinkListener(iControl);
return iControl;
} else {
return new DefaultInformationControl(parent, tooltipAffordanceString);
}
}
4. 下面是System.out.println的html内容和在firefox下显示的效果。
<html><head><style CHARSET="ISO-8859-1" TYPE="text/css">/* Font definitions */
html { font-family: 'Sans',sans-serif; font-size: 10pt; font-style: normal; font-weight: normal; }
body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt { font-size: 1em; }
pre { font-family: monospace; }
/* Margins */
body { overflow: auto; margin-top: 0px; margin-bottom: 0.5em; margin-left: 0.3em; margin-right: 0px; }
h1 { margin-top: 0.3em; margin-bottom: 0.04em; }
h2 { margin-top: 2em; margin-bottom: 0.25em; }
h3 { margin-top: 1.7em; margin-bottom: 0.25em; }
h4 { margin-top: 2em; margin-bottom: 0.3em; }
h5 { margin-top: 0px; margin-bottom: 0px; }
p { margin-top: 1em; margin-bottom: 1em; }
pre { margin-left: 0.6em; }
ul { margin-top: 0px; margin-bottom: 1em; margin-left: 1em; padding-left: 1em;}
li { margin-top: 0px; margin-bottom: 0px; }
li p { margin-top: 0px; margin-bottom: 0px; }
ol { margin-top: 0px; margin-bottom: 1em; margin-left: 1em; padding-left: 1em; }
dl { margin-top: 0px; margin-bottom: 1em; }
dt { margin-top: 0px; margin-bottom: 0px; font-weight: bold; }
dd { margin-top: 0px; margin-bottom: 0px; }
/* Styles and colors */
a:link { color: #0000FF; }
a:hover { color: #000080; }
a:visited { text-decoration: underline; }
a.header:link { text-decoration: none; color: #000000 }
a.header:visited { text-decoration: none; color: #000000 }
a.header:hover { text-decoration: underline; color: #000080; }
h4 { font-style: italic; }
strong { font-weight: bold; }
em { font-style: italic; }
var { font-style: italic; }
th { font-weight: bold; }
/* Workarounds for new Javadoc stylesheet (1.7) */
ul.blockList li.blockList, ul.blockListLast li.blockList {
list-style:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
list-style:none;
}
</style>
<base href='http://download.oracle.com/javase/7/docs/api/java/io/PrintStream.html'>
</head><body style="overflow:hidden;" text="#000000" bgcolor="#ffffbf"><h5><div style='word-wrap: break-word; position: relative; margin-left: 20px; padding-top: 2px; '><a href=''><!--[if lte IE 6]><![if gte IE 5.5]>
<span alt='Open Declaration' style="border:none; position: absolute; width: 16px; height: 16px; left: -21px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='')"></span>
<![endif]><![endif]-->
<!--[if !IE]>-->
<img alt='Open Declaration' style='border:none; position: absolute; width: 16px; height: 16px; left: -21px; ' src='/>
<!--<![endif]-->
<!--[if gte IE 7]>
<img alt='Open Declaration' style='border:none; position: absolute; width: 16px; height: 16px; left: -21px; ' src='file:'/>
<![endif]-->
</a>void <a class='header' href=''>java</a>.<a class='header' href=''>io</a>.<a class='header' href=''>PrintStream</a>.println(<span style='font-weight:normal;'></span>int x)</div></h5><br><p>Prints an integer and then terminate the line. This method behaves as
though it invokes <code><code><a href=''>print(int)</a></code></code> and then
<code><code><a href=''>println()</a></code></code>.<dl><dt>Parameters:</dt><dd><b>x</b> The <code>int</code> to be printed.</dd></dl></body></html>
显示效果: