1 11 package org.eclipse.jface.text.hyperlink; 12 13 import org.eclipse.swt.SWT; 14 import org.eclipse.swt.custom.StyleRange; 15 import org.eclipse.swt.custom.StyledText; 16 import org.eclipse.swt.graphics.Color; 17 import org.eclipse.swt.graphics.Cursor; 18 import org.eclipse.swt.graphics.RGB; 19 import org.eclipse.swt.widgets.Display; 20 21 import org.eclipse.core.runtime.Assert; 22 23 import org.eclipse.jface.preference.IPreferenceStore; 24 import org.eclipse.jface.preference.PreferenceConverter; 25 import org.eclipse.jface.util.IPropertyChangeListener; 26 import org.eclipse.jface.util.PropertyChangeEvent; 27 28 import org.eclipse.jface.text.BadLocationException; 29 import org.eclipse.jface.text.DocumentEvent; 30 import org.eclipse.jface.text.IDocument; 31 import org.eclipse.jface.text.IDocumentListener; 32 import org.eclipse.jface.text.IRegion; 33 import org.eclipse.jface.text.ITextInputListener; 34 import org.eclipse.jface.text.ITextPresentationListener; 35 import org.eclipse.jface.text.ITextViewer; 36 import org.eclipse.jface.text.ITextViewerExtension2; 37 import org.eclipse.jface.text.ITextViewerExtension4; 38 import org.eclipse.jface.text.Position; 39 import org.eclipse.jface.text.Region; 40 import org.eclipse.jface.text.TextPresentation; 41 42 43 54 public class DefaultHyperlinkPresenter implements IHyperlinkPresenter, ITextPresentationListener, ITextInputListener, IDocumentListener, IPropertyChangeListener { 55 56 66 public final static String HYPERLINK_COLOR= "hyperlinkColor"; 68 69 70 private ITextViewer fTextViewer; 71 72 private Cursor fCursor; 73 74 private Color fColor; 75 76 private RGB fRGB; 77 78 private boolean fDisposeColor; 79 80 private IRegion fActiveRegion; 81 82 private Position fRememberedPosition; 83 84 private IPreferenceStore fPreferenceStore; 85 86 87 93 public DefaultHyperlinkPresenter(IPreferenceStore store) { 94 fPreferenceStore= store; 95 fDisposeColor= true; 96 } 97 98 103 public DefaultHyperlinkPresenter(Color color) { 104 fDisposeColor= false; 105 fColor= color; 106 } 107 108 113 public DefaultHyperlinkPresenter(RGB color) { 114 fRGB= color; 115 fDisposeColor= true; 116 } 117 118 121 public boolean canShowMultipleHyperlinks() { 122 return false; 123 } 124 125 128 public void showHyperlinks(IHyperlink[] hyperlinks) { 129 Assert.isLegal(hyperlinks != null && hyperlinks.length == 1); 130 highlightRegion(hyperlinks[0].getHyperlinkRegion()); 131 activateCursor(); 132 } 133 134 137 public void hideHyperlinks() { 138 repairRepresentation(); 139 fRememberedPosition= null; 140 } 141 142 145 public void install(ITextViewer textViewer) { 146 Assert.isNotNull(textViewer); 147 fTextViewer= textViewer; 148 fTextViewer.addTextInputListener(this); 149 if (fTextViewer instanceof ITextViewerExtension4) 150 ((ITextViewerExtension4)fTextViewer).addTextPresentationListener(this); 151 152 StyledText text= fTextViewer.getTextWidget(); 153 if (text != null && !text.isDisposed()) { 154 if (fPreferenceStore != null) 155 fColor= createColor(fPreferenceStore, HYPERLINK_COLOR, text.getDisplay()); 156 else if (fRGB != null) 157 fColor= new Color(text.getDisplay(), fRGB); 158 } 159 160 if (fPreferenceStore != null) 161 fPreferenceStore.addPropertyChangeListener(this); 162 } 163 164 167 public void uninstall() { 168 fTextViewer.removeTextInputListener(this); 169 IDocument document= fTextViewer.getDocument(); 170 if (document != null) 171 document.removeDocumentListener(this); 172 173 if (fColor != null) { 174 if (fDisposeColor) 175 fColor.dispose(); 176 fColor= null; 177 } 178 179 if (fCursor != null) { 180 fCursor.dispose(); 181 fCursor= null; 182 } 183 184 if (fTextViewer instanceof ITextViewerExtension4) 185 ((ITextViewerExtension4)fTextViewer).removeTextPresentationListener(this); 186 fTextViewer= null; 187 188 if (fPreferenceStore != null) 189 fPreferenceStore.removePropertyChangeListener(this); 190 } 191 192 public void setColor(Color color) { 193 Assert.isNotNull(fTextViewer); 194 fColor= color; 195 } 196 197 200 public void applyTextPresentation(TextPresentation textPresentation) { 201 if (fActiveRegion == null) 202 return; 203 IRegion region= textPresentation.getExtent(); 204 if (fActiveRegion.getOffset() + fActiveRegion.getLength() >= region.getOffset() && region.getOffset() + region.getLength() > fActiveRegion.getOffset()) { 205 StyleRange styleRange= new StyleRange(fActiveRegion.getOffset(), fActiveRegion.getLength(), fColor, null); 206 styleRange.underline= true; 207 textPresentation.mergeStyleRange(styleRange); 208 } 209 } 210 211 private void highlightRegion(IRegion region) { 212 213 if (region.equals(fActiveRegion)) 214 return; 215 216 repairRepresentation(); 217 218 StyledText text= fTextViewer.getTextWidget(); 219 if (text == null || text.isDisposed()) 220 return; 221 222 fActiveRegion= region; 224 if (fTextViewer instanceof ITextViewerExtension2) 225 ((ITextViewerExtension2)fTextViewer).invalidateTextPresentation(region.getOffset(), region.getLength()); 226 else 227 fTextViewer.invalidateTextPresentation(); 228 } 229 230 private void activateCursor() { 231 StyledText text= fTextViewer.getTextWidget(); 232 if (text == null || text.isDisposed()) 233 return; 234 Display display= text.getDisplay(); 235 if (fCursor == null) 236 fCursor= new Cursor(display, SWT.CURSOR_HAND); 237 text.setCursor(fCursor); 238 } 239 240 private void resetCursor() { 241 StyledText text= fTextViewer.getTextWidget(); 242 if (text != null && !text.isDisposed()) 243 text.setCursor(null); 244 245 if (fCursor != null) { 246 fCursor.dispose(); 247 fCursor= null; 248 } 249 } 250 251 private void repairRepresentation() { 252 253 if (fActiveRegion == null) 254 return; 255 256 int offset= fActiveRegion.getOffset(); 257 int length= fActiveRegion.getLength(); 258 fActiveRegion= null; 259 260 resetCursor(); 261 262 if (fTextViewer instanceof ITextViewerExtension2) 264 ((ITextViewerExtension2) fTextViewer).invalidateTextPresentation(offset, length); 265 else 266 fTextViewer.invalidateTextPresentation(); 267 268 } 269 270 273 public void documentAboutToBeChanged(DocumentEvent event) { 274 if (fActiveRegion != null) { 275 fRememberedPosition= new Position(fActiveRegion.getOffset(), fActiveRegion.getLength()); 276 try { 277 event.getDocument().addPosition(fRememberedPosition); 278 } catch (BadLocationException x) { 279 fRememberedPosition= null; 280 } 281 } 282 } 283 284 287 public void documentChanged(DocumentEvent event) { 288 if (fRememberedPosition != null) { 289 if (!fRememberedPosition.isDeleted()) { 290 event.getDocument().removePosition(fRememberedPosition); 291 fActiveRegion= new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength()); 292 } else { 293 fActiveRegion= new Region(event.getOffset(), event.getLength()); 294 } 295 fRememberedPosition= null; 296 297 StyledText widget= fTextViewer.getTextWidget(); 298 if (widget != null && !widget.isDisposed()) { 299 widget.getDisplay().asyncExec(new Runnable () { 300 public void run() { 301 hideHyperlinks(); 302 } 303 }); 304 } 305 } 306 } 307 308 311 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 312 if (oldInput == null) 313 return; 314 hideHyperlinks(); 315 oldInput.removeDocumentListener(this); 316 } 317 318 321 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 322 if (newInput == null) 323 return; 324 newInput.addDocumentListener(this); 325 } 326 327 335 private Color createColor(IPreferenceStore store, String key, Display display) { 336 337 RGB rgb= null; 338 339 if (store.contains(key)) { 340 341 if (store.isDefault(key)) 342 rgb= PreferenceConverter.getDefaultColor(store, key); 343 else 344 rgb= PreferenceConverter.getColor(store, key); 345 346 if (rgb != null) 347 return new Color(display, rgb); 348 } 349 350 return null; 351 } 352 353 356 public void propertyChange(PropertyChangeEvent event) { 357 if (!HYPERLINK_COLOR.equals(event.getProperty())) 358 return; 359 360 if (fDisposeColor && fColor != null && !fColor.isDisposed()) 361 fColor.dispose(); 362 fColor= null; 363 364 StyledText textWidget= fTextViewer.getTextWidget(); 365 if (textWidget != null && !textWidget.isDisposed()) 366 fColor= createColor(fPreferenceStore, HYPERLINK_COLOR, textWidget.getDisplay()); 367 } 368 } 369 | Popular Tags |