1 11 package org.eclipse.ant.internal.ui.editor.text; 12 13 import java.util.Iterator ; 14 import java.util.StringTokenizer ; 15 16 import org.apache.tools.ant.BuildException; 17 import org.apache.tools.ant.Project; 18 import org.apache.tools.ant.types.AbstractFileSet; 19 import org.apache.tools.ant.types.Path; 20 import org.apache.tools.ant.types.PatternSet; 21 import org.eclipse.ant.internal.ui.debug.model.AntProperty; 22 import org.eclipse.ant.internal.ui.debug.model.AntStackFrame; 23 import org.eclipse.ant.internal.ui.debug.model.AntValue; 24 import org.eclipse.ant.internal.ui.editor.AntEditor; 25 import org.eclipse.ant.internal.ui.editor.AntEditorSourceViewerConfiguration; 26 import org.eclipse.ant.internal.ui.model.AntElementNode; 27 import org.eclipse.ant.internal.ui.model.AntModel; 28 import org.eclipse.ant.internal.ui.model.AntPropertyNode; 29 import org.eclipse.ant.internal.ui.model.IAntModel; 30 import org.eclipse.core.runtime.IAdaptable; 31 import org.eclipse.debug.ui.DebugUITools; 32 import org.eclipse.jface.internal.text.html.HTMLPrinter; 33 import org.eclipse.jface.internal.text.html.HTMLTextPresenter; 34 import org.eclipse.jface.text.BadLocationException; 35 import org.eclipse.jface.text.DefaultInformationControl; 36 import org.eclipse.jface.text.IDocument; 37 import org.eclipse.jface.text.IInformationControl; 38 import org.eclipse.jface.text.IInformationControlCreator; 39 import org.eclipse.jface.text.IRegion; 40 import org.eclipse.jface.text.ITextHover; 41 import org.eclipse.jface.text.ITextHoverExtension; 42 import org.eclipse.jface.text.ITextViewer; 43 import org.eclipse.jface.text.Position; 44 import org.eclipse.jface.text.Region; 45 import org.eclipse.jface.text.information.IInformationProviderExtension2; 46 import org.eclipse.jface.text.source.Annotation; 47 import org.eclipse.jface.text.source.IAnnotationModel; 48 import org.eclipse.jface.text.source.ISourceViewer; 49 import org.eclipse.swt.SWT; 50 import org.eclipse.swt.widgets.Shell; 51 import org.eclipse.ui.editors.text.EditorsUI; 52 53 54 public class XMLTextHover implements ITextHover, ITextHoverExtension, IInformationProviderExtension2 { 55 56 private AntEditor fEditor; 57 58 public XMLTextHover(AntEditor editor) { 59 super(); 60 fEditor = editor; 61 } 62 63 67 private String formatMessage(String message) { 68 StringBuffer buffer= new StringBuffer (); 69 HTMLPrinter.addPageProlog(buffer); 70 HTMLPrinter.addParagraph(buffer, message); 71 HTMLPrinter.addPageEpilog(buffer); 72 return buffer.toString(); 73 } 74 75 78 private String formatPathMessage(String [] list) { 79 StringBuffer buffer= new StringBuffer (); 80 HTMLPrinter.addPageProlog(buffer); 81 HTMLPrinter.addSmallHeader(buffer, AntEditorTextMessages.XMLTextHover_4); 82 HTMLPrinter.startBulletList(buffer); 83 for (int i = 0; i < list.length; i++) { 84 HTMLPrinter.addBullet(buffer, list[i]); 85 } 86 HTMLPrinter.endBulletList(buffer); 87 HTMLPrinter.addPageEpilog(buffer); 88 return buffer.toString(); 89 } 90 91 94 public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { 95 96 if (!(textViewer instanceof ISourceViewer)) { 97 return null; 98 } 99 100 ISourceViewer sourceViewer= (ISourceViewer) textViewer; 101 IAnnotationModel model= sourceViewer.getAnnotationModel(); 102 103 if (model != null) { 104 String message= getAnnotationModelHoverMessage(model, hoverRegion); 105 if (message != null) { 106 return message; 107 } 108 } 109 110 AntModel antModel= fEditor.getAntModel(); 111 if (antModel == null) { return null; 113 } 114 115 return getAntModelHoverMessage(antModel, hoverRegion, textViewer); 116 117 } 118 119 private String getAntModelHoverMessage(AntModel antModel, IRegion hoverRegion, ITextViewer textViewer){ 120 try { 121 IDocument document= textViewer.getDocument(); 122 int offset= hoverRegion.getOffset(); 123 int length= hoverRegion.getLength(); 124 String text= document.get(offset, length); 125 String value; 126 AntElementNode node= antModel.getNode(offset, false); 127 if (document.get(offset - 2, 2).equals("${") || node instanceof AntPropertyNode) { AntStackFrame frame= getFrame(); 129 if (frame != null) { AntProperty property= frame.findProperty(text); 131 if (property != null) { 132 return ((AntValue)property.getValue()).getValueString(); 133 } 134 } 135 value= antModel.getPropertyValue(text); 136 if (value != null) { 137 return formatMessage(HTMLPrinter.convertToHTMLContent(value)); 138 } 139 } 140 value= antModel.getTargetDescription(text); 141 if (value != null) { 142 return formatMessage(HTMLPrinter.convertToHTMLContent(value)); 143 } 144 Object referencedObject= antModel.getReferenceObject(text); 145 if (referencedObject != null) { 146 if (referencedObject instanceof Path) { 147 return formatPathMessage(((Path)referencedObject).list()); 148 } else if (referencedObject instanceof PatternSet) { 149 return formatPatternSetMessage((PatternSet) referencedObject); 150 } else if (referencedObject instanceof AbstractFileSet) { 151 return formatFileSetMessage((AbstractFileSet)referencedObject); 152 } 153 } 154 } catch (BadLocationException e) { 155 } catch (BuildException be) { 156 return be.getMessage(); 157 } 158 159 return null; 160 } 161 162 private String getAnnotationModelHoverMessage(IAnnotationModel model, IRegion hoverRegion) { 163 Iterator e= model.getAnnotationIterator(); 164 while (e.hasNext()) { 165 Annotation a= (Annotation) e.next(); 166 if (a instanceof XMLProblemAnnotation) { 167 Position p= model.getPosition(a); 168 if (p.overlapsWith(hoverRegion.getOffset(), hoverRegion.getLength())) { 169 String msg= a.getText(); 170 if (msg != null && msg.trim().length() > 0) { 171 return formatMessage(msg); 172 } 173 } 174 } 175 } 176 return null; 177 } 178 179 private String formatFileSetMessage(AbstractFileSet set) { 180 FileScanner fileScanner= new FileScanner(); 181 IAntModel antModel= fEditor.getAntModel(); 182 Project project= antModel.getProjectNode().getProject(); 183 set.setupDirectoryScanner(fileScanner, project); 184 String [] excludedPatterns= fileScanner.getExcludesPatterns(); 185 String [] includesPatterns= fileScanner.getIncludePatterns(); 186 return formatSetMessage(includesPatterns, excludedPatterns); 187 } 188 189 private String formatPatternSetMessage(PatternSet set) { 190 IAntModel antModel= fEditor.getAntModel(); 191 Project project= antModel.getProjectNode().getProject(); 192 String [] includes= set.getIncludePatterns(project); 193 String [] excludes= set.getExcludePatterns(project); 194 return formatSetMessage(includes, excludes); 195 } 196 197 private String formatSetMessage(String [] includes, String [] excludes) { 198 StringBuffer buffer= new StringBuffer (); 199 HTMLPrinter.addPageProlog(buffer); 200 if (includes != null && includes.length > 0) { 201 HTMLPrinter.addSmallHeader(buffer, AntEditorTextMessages.XMLTextHover_5); 202 for (int i = 0; i < includes.length; i++) { 203 HTMLPrinter.addBullet(buffer, includes[i]); 204 } 205 } 206 HTMLPrinter.addParagraph(buffer, ""); HTMLPrinter.addParagraph(buffer, ""); if (excludes != null && excludes.length > 0) { 209 HTMLPrinter.addSmallHeader(buffer, AntEditorTextMessages.XMLTextHover_6); 210 for (int i = 0; i < excludes.length; i++) { 211 HTMLPrinter.addBullet(buffer, excludes[i]); 212 } 213 } 214 HTMLPrinter.addPageEpilog(buffer); 215 return buffer.toString(); 216 } 217 218 221 public IRegion getHoverRegion(ITextViewer textViewer, int offset) { 222 if (textViewer != null) { 223 return getRegion(textViewer, offset); 224 } 225 return null; 226 } 227 228 public static IRegion getRegion(ITextViewer textViewer, int offset) { 229 IDocument document= textViewer.getDocument(); 230 231 int start= -1; 232 int end= -1; 233 IRegion region= null; 234 try { 235 int pos= offset; 236 char c; 237 238 if (document.getChar(pos) == '"') { 239 pos--; 240 } 241 while (pos >= 0) { 242 c= document.getChar(pos); 243 if (c != '.' && c != '-' && c != '/' && c != '\\' && c != ' ' && c != ')' && c != '('&& c != ':' && !Character.isJavaIdentifierPart(c) && pos != offset) 244 break; 245 --pos; 246 } 247 248 start= pos; 249 250 pos= offset; 251 int length= document.getLength(); 252 253 while (pos < length) { 254 c= document.getChar(pos); 255 if (c != '.' && c != '-' && c != '/' && c != '\\' && c != ' ' && c != ')' && c != '('&& c != ':' && !Character.isJavaIdentifierPart(c)) 256 break; 257 if (c == '/' && (document.getLength() - 1) > (pos + 1) && document.getChar(pos + 1) == '>') { 258 break; 260 } 261 ++pos; 262 } 263 264 end= pos; 265 266 } catch (BadLocationException x) { 267 } 268 269 if (start > -1 && end > -1) { 270 if (start == offset && end == offset) { 271 return new Region(offset, 0); 272 } else if (start == offset) { 273 return new Region(start, end - start); 274 } else { 275 try { while(document.getChar(start + 1) == ' ') { 277 start++; 278 } 279 while(document.getChar(end - 1) == ' ') { 280 end--; 281 } 282 } catch (BadLocationException e) { 283 } 284 region= new Region(start + 1, end - start - 1); 285 } 286 } 287 288 if (region != null) { 289 try { 290 char c= document.getChar(region.getOffset() - 1); 291 if (c == '"') { 292 if (document.get(offset, region.getLength()).indexOf(',') != -1) { 293 region = cleanRegionForNonProperty(offset, document, region); 294 } 295 } else if (c != '{') { 296 region = cleanRegionForNonProperty(offset, document, region); 297 } 298 } catch (BadLocationException e) { 299 } 300 } 301 302 return region; 303 } 304 305 private static IRegion cleanRegionForNonProperty(int offset, IDocument document, IRegion region) throws BadLocationException { 306 String text= document.get(region.getOffset(), region.getLength()); 308 if (text.startsWith("/")) { text= text.substring(1); 310 region= new Region(region.getOffset() + 1, region.getLength() - 1); 311 } 312 StringTokenizer tokenizer= new StringTokenizer (text, " "); if (tokenizer.countTokens() != 1) { 314 while(tokenizer.hasMoreTokens()) { 315 String token= tokenizer.nextToken(); 316 int index= text.indexOf(token); 317 if (region.getOffset() + index <= offset && region.getOffset() + index + token.length() >= offset) { 318 region= new Region(region.getOffset() + index, token.length()); 319 break; 320 } 321 } 322 } 323 324 return region; 325 } 326 327 330 public IInformationControlCreator getHoverControlCreator() { 331 return new IInformationControlCreator() { 332 public IInformationControl createInformationControl(Shell parent) { 333 return new DefaultInformationControl(parent, SWT.NONE, 334 new HTMLTextPresenter(true), 335 EditorsUI.getTooltipAffordanceString()); 336 } 337 }; 338 } 339 340 347 private AntStackFrame getFrame() { 348 IAdaptable adaptable = DebugUITools.getDebugContext(); 349 if (adaptable != null) { 350 return (AntStackFrame)adaptable.getAdapter(AntStackFrame.class); 351 } 352 return null; 353 } 354 355 359 public IInformationControlCreator getInformationPresenterControlCreator() { 360 return AntEditorSourceViewerConfiguration.getInformationPresenterControlCreator(); 361 } 362 363 } 364 | Popular Tags |