1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.ui.text.java.hover;
 
  13 import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
 
  14 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  15 import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
 
  17 import org.eclipse.jface.preference.IPreferenceStore;
 
  18 import org.eclipse.jface.text.Document;
 
  19 import org.eclipse.jface.text.IDocument;
 
  20 import org.eclipse.jface.text.IInformationControl;
 
  21 import org.eclipse.jface.text.IInformationControlExtension;
 
  22 import org.eclipse.jface.text.source.ISourceViewer;
 
  23 import org.eclipse.jface.text.source.SourceViewer;
 
  24 import org.eclipse.swt.SWT;
 
  25 import org.eclipse.swt.custom.StyledText;
 
  26 import org.eclipse.swt.events.DisposeEvent;
 
  27 import org.eclipse.swt.events.DisposeListener;
 
  28 import org.eclipse.swt.events.FocusListener;
 
  29 import org.eclipse.swt.events.KeyEvent;
 
  30 import org.eclipse.swt.events.KeyListener;
 
  31 import org.eclipse.swt.graphics.Color;
 
  32 import org.eclipse.swt.graphics.Font;
 
  33 import org.eclipse.swt.graphics.FontData;
 
  34 import org.eclipse.swt.graphics.Point;
 
  35 import org.eclipse.swt.graphics.Rectangle;
 
  36 import org.eclipse.swt.layout.GridData;
 
  37 import org.eclipse.swt.layout.GridLayout;
 
  38 import org.eclipse.swt.widgets.Composite;
 
  39 import org.eclipse.swt.widgets.Display;
 
  40 import org.eclipse.swt.widgets.Label;
 
  41 import org.eclipse.swt.widgets.Shell;
 
  44  * Source viewer based implementation of <code>IInformationControl</code>.
 
  45  * Displays information in a source viewer.
 
  49 public class SourceViewerInformationControl implements IInformationControl,
 
  50                 IInformationControlExtension, DisposeListener {
 
  52         /** Border thickness in pixels. */
 
  53         private static final int BORDER = 1;
 
  55         /** The control's shell */
 
  58         /** The control's text widget */
 
  59         private StyledText fText;
 
  61         /** The control's source viewer */
 
  62         private SourceViewer fViewer;
 
  65          * The optional status field.
 
  69         private Label fStatusField;
 
  72          * The separator for the optional status field.
 
  76         private Label fSeparator;
 
  79          * The font of the optional status text label.
 
  83         private Font fStatusTextFont;
 
  86          * Creates a default information control with the given shell as parent. The
 
  87          * given information presenter is used to process the information to be
 
  88          * displayed. The given styles are applied to the created styled text
 
  94          *            the additional styles for the shell
 
  96          *            the additional styles for the styled text widget
 
  98         public SourceViewerInformationControl(Shell parent, int shellStyle,
 
 100                 this(parent, shellStyle, style, null);
 
 104          * Creates a default information control with the given shell as parent. The
 
 105          * given information presenter is used to process the information to be
 
 106          * displayed. The given styles are applied to the created styled text
 
 112          *            the additional styles for the shell
 
 114          *            the additional styles for the styled text widget
 
 115          * @param statusFieldText
 
 116          *            the text to be used in the optional status field or
 
 117          *            <code>null</code> if the status field should be hidden
 
 120         public SourceViewerInformationControl(Shell parent, int shellStyle,
 
 121                         int style, String statusFieldText) {
 
 125                 fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle);
 
 126                 Display display = fShell.getDisplay();
 
 127                 fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
 
 129                 Composite composite = fShell;
 
 130                 layout = new GridLayout(1, false);
 
 131                 int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
 
 132                 layout.marginHeight = border;
 
 133                 layout.marginWidth = border;
 
 134                 composite.setLayout(layout);
 
 135                 gd = new GridData(GridData.FILL_HORIZONTAL);
 
 136                 composite.setLayoutData(gd);
 
 138                 if (statusFieldText != null) {
 
 139                         composite = new Composite(composite, SWT.NONE);
 
 140                         layout = new GridLayout(1, false);
 
 141                         layout.marginHeight = 0;
 
 142                         layout.marginWidth = 0;
 
 143                         composite.setLayout(layout);
 
 144                         gd = new GridData(GridData.FILL_BOTH);
 
 145                         composite.setLayoutData(gd);
 
 146                         composite.setForeground(display
 
 147                                         .getSystemColor(SWT.COLOR_INFO_FOREGROUND));
 
 148                         composite.setBackground(display
 
 149                                         .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
 
 153                 IPreferenceStore store = PHPeclipsePlugin.getDefault()
 
 154                                 .getCombinedPreferenceStore();
 
 155                 fViewer = new JavaSourceViewer(composite, null, null, false, style,
 
 157                 fViewer.configure(new PHPSourceViewerConfiguration(PHPeclipsePlugin
 
 158                                 .getDefault().getJavaTextTools().getColorManager(), store,
 
 160                 fViewer.setEditable(false);
 
 162                 fText = fViewer.getTextWidget();
 
 163                 gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
 
 164                 fText.setLayoutData(gd);
 
 165                 fText.setForeground(parent.getDisplay().getSystemColor(
 
 166                                 SWT.COLOR_INFO_FOREGROUND));
 
 167                 fText.setBackground(parent.getDisplay().getSystemColor(
 
 168                                 SWT.COLOR_INFO_BACKGROUND));
 
 170                 fText.addKeyListener(new KeyListener() {
 
 172                         public void keyPressed(KeyEvent e) {
 
 173                                 if (e.character == 0x1B) // ESC
 
 177                         public void keyReleased(KeyEvent e) {
 
 182                 if (statusFieldText != null) {
 
 184                         // Horizontal separator line
 
 185                         fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL
 
 187                         fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 189                         // Status field label
 
 190                         fStatusField = new Label(composite, SWT.RIGHT);
 
 191                         fStatusField.setText(statusFieldText);
 
 192                         Font font = fStatusField.getFont();
 
 193                         FontData[] fontDatas = font.getFontData();
 
 194                         for (int i = 0; i < fontDatas.length; i++)
 
 195                                 fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
 
 196                         fStatusTextFont = new Font(fStatusField.getDisplay(), fontDatas);
 
 197                         fStatusField.setFont(fStatusTextFont);
 
 198                         GridData gd2 = new GridData(GridData.FILL_VERTICAL
 
 199                                         | GridData.FILL_HORIZONTAL
 
 200                                         | GridData.HORIZONTAL_ALIGN_BEGINNING
 
 201                                         | GridData.VERTICAL_ALIGN_BEGINNING);
 
 202                         fStatusField.setLayoutData(gd2);
 
 204                         // Regarding the color see bug 41128
 
 205                         fStatusField.setForeground(display
 
 206                                         .getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
 
 208                         fStatusField.setBackground(display
 
 209                                         .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
 
 212                 addDisposeListener(this);
 
 216          * Creates a default information control with the given shell as parent. The
 
 217          * given information presenter is used to process the information to be
 
 218          * displayed. The given styles are applied to the created styled text
 
 224          *            the additional styles for the styled text widget
 
 226         public SourceViewerInformationControl(Shell parent, int style) {
 
 227                 this(parent, SWT.NO_TRIM, style);
 
 231          * Creates a default information control with the given shell as parent. The
 
 232          * given information presenter is used to process the information to be
 
 233          * displayed. The given styles are applied to the created styled text
 
 239          *            the additional styles for the styled text widget
 
 240          * @param statusFieldText
 
 241          *            the text to be used in the optional status field or
 
 242          *            <code>null</code> if the status field should be hidden
 
 245         public SourceViewerInformationControl(Shell parent, int style,
 
 246                         String statusFieldText) {
 
 247                 this(parent, SWT.NO_TRIM, style, statusFieldText);
 
 251          * Creates a default information control with the given shell as parent. No
 
 252          * information presenter is used to process the information to be displayed.
 
 253          * No additional styles are applied to the styled text widget.
 
 258         public SourceViewerInformationControl(Shell parent) {
 
 259                 this(parent, SWT.NONE);
 
 263          * Creates a default information control with the given shell as parent. No
 
 264          * information presenter is used to process the information to be displayed.
 
 265          * No additional styles are applied to the styled text widget.
 
 269          * @param statusFieldText
 
 270          *            the text to be used in the optional status field or
 
 271          *            <code>null</code> if the status field should be hidden
 
 274         public SourceViewerInformationControl(Shell parent, String statusFieldText) {
 
 275                 this(parent, SWT.NONE, statusFieldText);
 
 279          * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
 
 281         public void setInput(Object input) {
 
 282                 if (input instanceof String)
 
 283                         setInformation((String) input);
 
 285                         setInformation(null);
 
 289          * @see IInformationControl#setInformation(String)
 
 291         public void setInformation(String content) {
 
 292                 if (content == null) {
 
 293                         fViewer.setInput(null);
 
 297                 IDocument doc = new Document(content);
 
 298                 PHPeclipsePlugin.getDefault().getJavaTextTools()
 
 299                                 .setupJavaDocumentPartitioner(doc);
 
 301                 fViewer.setInput(doc);
 
 305          * @see IInformationControl#setVisible(boolean)
 
 307         public void setVisible(boolean visible) {
 
 308                 fShell.setVisible(visible);
 
 316         public void widgetDisposed(DisposeEvent event) {
 
 317                 if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
 
 318                         fStatusTextFont.dispose();
 
 320                 fStatusTextFont = null;
 
 328         public final void dispose() {
 
 329                 if (fShell != null && !fShell.isDisposed())
 
 332                         widgetDisposed(null);
 
 336          * @see IInformationControl#setSize(int, int)
 
 338         public void setSize(int width, int height) {
 
 340                 if (fStatusField != null) {
 
 341                         GridData gd = (GridData) fViewer.getTextWidget().getLayoutData();
 
 342                         Point statusSize = fStatusField.computeSize(SWT.DEFAULT,
 
 344                         Point separatorSize = fSeparator.computeSize(SWT.DEFAULT,
 
 346                         gd.heightHint = height - statusSize.y - separatorSize.y;
 
 348                 fShell.setSize(width, height);
 
 350                 if (fStatusField != null)
 
 355          * @see IInformationControl#setLocation(Point)
 
 357         public void setLocation(Point location) {
 
 358                 Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
 
 359                 Point textLocation = fText.getLocation();
 
 360                 location.x += trim.x - textLocation.x;
 
 361                 location.y += trim.y - textLocation.y;
 
 362                 fShell.setLocation(location);
 
 366          * @see IInformationControl#setSizeConstraints(int, int)
 
 368         public void setSizeConstraints(int maxWidth, int maxHeight) {
 
 369                 maxWidth = maxHeight;
 
 373          * @see IInformationControl#computeSizeHint()
 
 375         public Point computeSizeHint() {
 
 376                 return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
 
 380          * @see IInformationControl#addDisposeListener(DisposeListener)
 
 382         public void addDisposeListener(DisposeListener listener) {
 
 383                 fShell.addDisposeListener(listener);
 
 387          * @see IInformationControl#removeDisposeListener(DisposeListener)
 
 389         public void removeDisposeListener(DisposeListener listener) {
 
 390                 fShell.removeDisposeListener(listener);
 
 394          * @see IInformationControl#setForegroundColor(Color)
 
 396         public void setForegroundColor(Color foreground) {
 
 397                 fText.setForeground(foreground);
 
 401          * @see IInformationControl#setBackgroundColor(Color)
 
 403         public void setBackgroundColor(Color background) {
 
 404                 fText.setBackground(background);
 
 408          * @see IInformationControl#isFocusControl()
 
 410         public boolean isFocusControl() {
 
 411                 return fText.isFocusControl();
 
 415          * @see IInformationControl#setFocus()
 
 417         public void setFocus() {
 
 423          * @see IInformationControl#addFocusListener(FocusListener)
 
 425         public void addFocusListener(FocusListener listener) {
 
 426                 fText.addFocusListener(listener);
 
 430          * @see IInformationControl#removeFocusListener(FocusListener)
 
 432         public void removeFocusListener(FocusListener listener) {
 
 433                 fText.removeFocusListener(listener);
 
 437          * @see IInformationControlExtension#hasContents()
 
 439         public boolean hasContents() {
 
 440                 return fText.getCharCount() > 0;
 
 443         protected ISourceViewer getViewer() {