1 11 12 package org.eclipse.jdt.internal.ui.text.java.hover; 13 14 import java.io.IOException ; 15 import java.io.StringReader ; 16 import java.util.Iterator ; 17 18 import org.eclipse.core.runtime.ListenerList; 19 20 import org.eclipse.swt.SWT; 21 import org.eclipse.swt.SWTError; 22 import org.eclipse.swt.browser.Browser; 23 import org.eclipse.swt.browser.LocationAdapter; 24 import org.eclipse.swt.browser.LocationEvent; 25 import org.eclipse.swt.custom.StyleRange; 26 import org.eclipse.swt.events.DisposeEvent; 27 import org.eclipse.swt.events.DisposeListener; 28 import org.eclipse.swt.events.FocusEvent; 29 import org.eclipse.swt.events.FocusListener; 30 import org.eclipse.swt.events.KeyEvent; 31 import org.eclipse.swt.events.KeyListener; 32 import org.eclipse.swt.graphics.Color; 33 import org.eclipse.swt.graphics.Font; 34 import org.eclipse.swt.graphics.FontData; 35 import org.eclipse.swt.graphics.Point; 36 import org.eclipse.swt.graphics.Rectangle; 37 import org.eclipse.swt.graphics.TextLayout; 38 import org.eclipse.swt.graphics.TextStyle; 39 import org.eclipse.swt.layout.GridData; 40 import org.eclipse.swt.layout.GridLayout; 41 import org.eclipse.swt.widgets.Composite; 42 import org.eclipse.swt.widgets.Display; 43 import org.eclipse.swt.widgets.Event; 44 import org.eclipse.swt.widgets.Label; 45 import org.eclipse.swt.widgets.Listener; 46 import org.eclipse.swt.widgets.Menu; 47 import org.eclipse.swt.widgets.Shell; 48 49 import org.eclipse.jface.text.IInformationControl; 50 import org.eclipse.jface.text.IInformationControlExtension; 51 import org.eclipse.jface.text.IInformationControlExtension3; 52 import org.eclipse.jface.text.TextPresentation; 53 54 import org.eclipse.jdt.internal.ui.JavaPlugin; 55 import org.eclipse.jdt.internal.ui.text.HTML2TextReader; 56 import org.eclipse.jdt.internal.ui.text.HTMLPrinter; 57 import org.eclipse.jdt.internal.ui.text.IInformationControlExtension4; 58 59 60 75 public class BrowserInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension3, IInformationControlExtension4, DisposeListener { 76 77 78 85 public static boolean isAvailable(Composite parent) { 86 if (!fgAvailabilityChecked) { 87 try { 88 if (parent == null) 89 parent= JavaPlugin.getActiveWorkbenchShell(); 90 if (parent == null) 91 return false; 93 Browser browser= new Browser(parent, SWT.NONE); 94 browser.dispose(); 95 fgIsAvailable= true; 96 } catch (SWTError er) { 97 fgIsAvailable= false; 98 } finally { 99 fgAvailabilityChecked= true; 100 } 101 } 102 103 return fgIsAvailable; 104 } 105 106 107 108 private static final int BORDER= 1; 109 110 114 private static final int MIN_WIDTH= 80; 115 private static final int MIN_HEIGHT= 80; 116 117 118 121 private static boolean fgIsAvailable= false; 122 private static boolean fgAvailabilityChecked= false; 123 124 125 private Shell fShell; 126 127 private Browser fBrowser; 128 129 private boolean fBrowserHasContent; 130 131 private int fMaxWidth= -1; 132 133 private int fMaxHeight= -1; 134 private Font fStatusTextFont; 135 private Label fStatusTextField; 136 private String fStatusFieldText; 137 private boolean fHideScrollBars; 138 private Listener fDeactivateListener; 139 private ListenerList fFocusListeners= new ListenerList(); 140 private Label fSeparator; 141 private String fInputText; 142 private TextLayout fTextLayout; 143 144 private TextStyle fBoldStyle; 145 146 155 public BrowserInformationControl(Shell parent, int shellStyle, int style) { 156 this(parent, shellStyle, style, null); 157 } 158 159 170 public BrowserInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) { 171 fStatusFieldText= statusFieldText; 172 173 fShell= new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); 174 Display display= fShell.getDisplay(); 175 fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); 176 fTextLayout= new TextLayout(display); 177 178 Composite composite= fShell; 179 GridLayout layout= new GridLayout(1, false); 180 int border= ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; 181 layout.marginHeight= border; 182 layout.marginWidth= border; 183 composite.setLayout(layout); 184 185 if (statusFieldText != null) { 186 composite= new Composite(composite, SWT.NONE); 187 layout= new GridLayout(1, false); 188 layout.marginHeight= 0; 189 layout.marginWidth= 0; 190 layout.verticalSpacing= 1; 191 layout.horizontalSpacing= 1; 192 composite.setLayout(layout); 193 194 GridData gd= new GridData(GridData.FILL_BOTH); 195 composite.setLayoutData(gd); 196 197 composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); 198 composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 199 } 200 201 fBrowser= new Browser(composite, SWT.NONE); 203 fHideScrollBars= (style & SWT.V_SCROLL) == 0 && (style & SWT.H_SCROLL) == 0; 204 205 GridData gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH); 206 fBrowser.setLayoutData(gd); 207 208 fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); 209 fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 210 fBrowser.addKeyListener(new KeyListener() { 211 212 public void keyPressed(KeyEvent e) { 213 if (e.character == 0x1B) fShell.dispose(); 215 } 216 217 public void keyReleased(KeyEvent e) {} 218 }); 219 225 fBrowser.addLocationListener(new LocationAdapter() { 226 229 public void changing(LocationEvent event) { 230 String location= event.location; 231 237 if (!"about:blank".equals(location) && !("carbon".equals(SWT.getPlatform()) && location.startsWith("applewebdata:"))) event.doit= false; 239 } 240 }); 241 242 fBrowser.setMenu(new Menu(fShell, SWT.NONE)); 244 245 if (statusFieldText != null) { 247 248 fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); 249 fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 250 251 fStatusTextField= new Label(composite, SWT.RIGHT); 253 fStatusTextField.setText(statusFieldText); 254 Font font= fStatusTextField.getFont(); 255 FontData[] fontDatas= font.getFontData(); 256 for (int i= 0; i < fontDatas.length; i++) 257 fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); 258 fStatusTextFont= new Font(fStatusTextField.getDisplay(), fontDatas); 259 fStatusTextField.setFont(fStatusTextFont); 260 gd= new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); 261 fStatusTextField.setLayoutData(gd); 262 263 fStatusTextField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); 264 265 fStatusTextField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 266 } 267 268 addDisposeListener(this); 269 createTextLayout(); 270 } 271 272 280 public BrowserInformationControl(Shell parent,int style) { 281 this(parent, SWT.TOOL | SWT.NO_TRIM, style); 282 } 283 284 291 public BrowserInformationControl(Shell parent) { 292 this(parent, SWT.NONE); 293 } 294 295 296 299 public void setInformation(String content) { 300 fBrowserHasContent= content != null && content.length() > 0; 301 302 if (!fBrowserHasContent) 303 content= "<html><body ></html>"; 305 fInputText= content; 306 307 int shellStyle= fShell.getStyle(); 308 boolean RTL= (shellStyle & SWT.RIGHT_TO_LEFT) != 0; 309 310 String [] styles= null; 311 if (RTL && !fHideScrollBars) 312 styles= new String [] { "direction:rtl;", "word-wrap:break-word;" }; else if (RTL && fHideScrollBars) 314 styles= new String [] { "direction:rtl;", "overflow:hidden;", "word-wrap:break-word;" }; else if (fHideScrollBars && true) 316 styles= new String [] { "overflow:hidden;", "word-wrap: break-word;" }; 318 if (styles != null) { 319 StringBuffer buffer= new StringBuffer (content); 320 HTMLPrinter.insertStyles(buffer, styles); 321 content= buffer.toString(); 322 } 323 324 fBrowser.setText(content); 325 326 } 327 328 332 public void setStatusText(String statusFieldText) { 333 fStatusFieldText= statusFieldText; 334 } 335 336 339 public void setVisible(boolean visible) { 340 if (fShell.isVisible() == visible) 341 return; 342 343 if (visible) { 344 if (fStatusTextField != null) { 345 boolean state= fStatusFieldText != null; 346 if (state) 347 fStatusTextField.setText(fStatusFieldText); 348 fStatusTextField.setVisible(state); 349 fSeparator.setVisible(state); 350 } 351 } 352 353 fShell.setVisible(visible); 354 if (!visible) 355 setInformation(""); } 357 358 364 private void createTextLayout() { 365 fTextLayout= new TextLayout(fBrowser.getDisplay()); 366 367 Font font= fBrowser.getFont(); 369 fTextLayout.setFont(font); 370 fTextLayout.setWidth(-1); 371 FontData[] fontData= font.getFontData(); 372 for (int i= 0; i < fontData.length; i++) 373 fontData[i].setStyle(SWT.BOLD); 374 font= new Font(fShell.getDisplay(), fontData); 375 fBoldStyle= new TextStyle(font, null, null); 376 377 fTextLayout.setText(" "); int tabWidth = fTextLayout.getBounds().width; 380 fTextLayout.setTabs(new int[] {tabWidth}); 381 382 fTextLayout.setText(""); } 384 385 388 public void dispose() { 389 fTextLayout.dispose(); 390 fTextLayout= null; 391 fBoldStyle.font.dispose(); 392 fBoldStyle= null; 393 if (fShell != null && !fShell.isDisposed()) 394 fShell.dispose(); 395 else 396 widgetDisposed(null); 397 } 398 399 402 public void widgetDisposed(DisposeEvent event) { 403 if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) 404 fStatusTextFont.dispose(); 405 406 fShell= null; 407 fBrowser= null; 408 fStatusTextFont= null; 409 } 410 411 414 public void setSize(int width, int height) { 415 fShell.setSize(Math.min(width, fMaxWidth), Math.min(height, fMaxHeight)); 416 } 417 418 421 public void setLocation(Point location) { 422 fShell.setLocation(location); 423 } 424 425 428 public void setSizeConstraints(int maxWidth, int maxHeight) { 429 fMaxWidth= maxWidth; 430 fMaxHeight= maxHeight; 431 } 432 433 436 public Point computeSizeHint() { 437 TextPresentation presentation= new TextPresentation(); 438 HTML2TextReader reader= new HTML2TextReader(new StringReader (fInputText), presentation); 439 String text; 440 try { 441 text= reader.getString(); 442 } catch (IOException e) { 443 text= ""; } 445 446 fTextLayout.setText(text); 447 Iterator iter= presentation.getAllStyleRangeIterator(); 448 while (iter.hasNext()) { 449 StyleRange sr= (StyleRange)iter.next(); 450 if (sr.fontStyle == SWT.BOLD) 451 fTextLayout.setStyle(fBoldStyle, sr.start, sr.start + sr.length - 1); 452 } 453 Rectangle bounds= fTextLayout.getBounds(); 454 int width= bounds.width; 455 int height= bounds.height; 456 457 width += 15; 458 height += 25; 459 460 if (fStatusFieldText != null && fSeparator != null) { 461 fTextLayout.setText(fStatusFieldText); 462 Rectangle statusBounds= fTextLayout.getBounds(); 463 Rectangle separatorBounds= fSeparator.getBounds(); 464 width= Math.max(width, statusBounds.width); 465 height= height + statusBounds.height + separatorBounds.height; 466 } 467 468 if (fMaxWidth != SWT.DEFAULT) 470 width= Math.min(fMaxWidth, width); 471 if (fMaxHeight != SWT.DEFAULT) 472 height= Math.min(fMaxHeight, height); 473 474 width= Math.max(MIN_WIDTH, width); 476 height= Math.max(MIN_HEIGHT, height); 477 478 return new Point(width, height); 479 } 480 481 484 public Rectangle computeTrim() { 485 return fShell.computeTrim(0, 0, 0, 0); 486 } 487 488 491 public Rectangle getBounds() { 492 return fShell.getBounds(); 493 } 494 495 498 public boolean restoresLocation() { 499 return false; 500 } 501 502 505 public boolean restoresSize() { 506 return false; 507 } 508 509 512 public void addDisposeListener(DisposeListener listener) { 513 fShell.addDisposeListener(listener); 514 } 515 516 519 public void removeDisposeListener(DisposeListener listener) { 520 fShell.removeDisposeListener(listener); 521 } 522 523 526 public void setForegroundColor(Color foreground) { 527 fBrowser.setForeground(foreground); 528 } 529 530 533 public void setBackgroundColor(Color background) { 534 fBrowser.setBackground(background); 535 } 536 537 540 public boolean isFocusControl() { 541 return fBrowser.isFocusControl(); 542 } 543 544 547 public void setFocus() { 548 fShell.forceFocus(); 549 fBrowser.setFocus(); 550 } 551 552 555 public void addFocusListener(final FocusListener listener) { 556 fBrowser.addFocusListener(listener); 557 558 562 if (fFocusListeners.isEmpty()) { 563 fDeactivateListener= new Listener() { 564 public void handleEvent(Event event) { 565 Object [] listeners= fFocusListeners.getListeners(); 566 for (int i = 0; i < listeners.length; i++) 567 ((FocusListener)listeners[i]).focusLost(new FocusEvent(event)); 568 } 569 }; 570 fBrowser.getShell().addListener(SWT.Deactivate, fDeactivateListener); 571 } 572 fFocusListeners.add(listener); 573 } 574 575 578 public void removeFocusListener(FocusListener listener) { 579 fBrowser.removeFocusListener(listener); 580 581 585 fFocusListeners.remove(listener); 586 if (fFocusListeners.isEmpty()) { 587 fBrowser.getShell().removeListener(SWT.Deactivate, fDeactivateListener); 588 fDeactivateListener= null; 589 } 590 } 591 592 595 public boolean hasContents() { 596 return fBrowserHasContent; 597 } 598 } 599 600 | Popular Tags |