/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.internal.text.html;

import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.ProgressAdapter;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.ToolBar;

import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IDelayedInputChangeProvider;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlExtension;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.text.IInformationControlExtension3;
import org.eclipse.jface.text.IInformationControlExtension4;
import org.eclipse.jface.text.IInformationControlExtension5;
import org.eclipse.jface.text.IInputChangedListener;
import org.eclipse.jface.text.TextPresentation;


/**
 * Displays HTML information in a {@link org.eclipse.swt.browser.Browser} widget.
 * <p>
 * This {@link IInformationControlExtension2} expects {@link #setInput(Object)} to be
 * called with an argument of type {@link BrowserInformationControlInput}.
 * </p>
 * <p>
 * Moved into this package from <code>org.eclipse.jface.internal.text.revisions</code>.</p>
 * <p>
 * This class may be instantiated; it is not intended to be subclassed.</p>
 * <p>
 * Current problems:
 * <ul>
 * 	<li>the size computation is too small</li>
 * 	<li>focusLost event is not sent - see https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532</li>
 * </ul>
 * </p>
 * 
 * @since 3.2
 */
public class BrowserInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension2, IInformationControlExtension3, IInformationControlExtension4, IInformationControlExtension5, IDelayedInputChangeProvider, DisposeListener {


	/**
	 * Tells whether the SWT Browser widget and hence this information
	 * control is available.
	 *
	 * @param parent the parent component used for checking or <code>null</code> if none
	 * @return <code>true</code> if this control is available
	 */
	public static boolean isAvailable(Composite parent) {
		if (!fgAvailabilityChecked) {
			try {
				Browser browser= new Browser(parent, SWT.NONE);
				browser.dispose();
				fgIsAvailable= true;
				
				Slider sliderV= new Slider(parent, SWT.VERTICAL);
				Slider sliderH= new Slider(parent, SWT.HORIZONTAL);
				int width= sliderV.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
				int height= sliderH.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
				fgScrollBarSize= new Point(width, height);
				sliderV.dispose();
				sliderH.dispose();
			} catch (SWTError er) {
				fgIsAvailable= false;
			} finally {
				fgAvailabilityChecked= true;
			}
		}

		return fgIsAvailable;
	}


	/** Border thickness in pixels. */
	private static final int BORDER= 1;
	
	/**
	 * Minimal size constraints.
	 * @since 3.2
	 */
	private static final int MIN_WIDTH= 80;
	private static final int MIN_HEIGHT= 50;

	
	/**
	 * Availability checking cache.
	 */
	private static boolean fgIsAvailable= false;
	private static boolean fgAvailabilityChecked= false;

	/**
	 * Cached scroll bar width and height
	 * @since 3.4
	 */
	private static Point fgScrollBarSize;
	
	/** The control's shell */
	private Shell fShell;
	/** The control's browser widget */
	private Browser fBrowser;
	/** Tells whether the browser has content */
	private boolean fBrowserHasContent;
	/** The control width constraint */
	private int fMaxWidth= SWT.DEFAULT;
	/** The control height constraint */
	private int fMaxHeight= SWT.DEFAULT;
	
	private Label fSeparator;
	private Font fStatusTextFont;
	private Label fStatusTextField;
	private String fStatusFieldText;
	
	private ToolBarManager fToolBarManager;
	private Label fTBSeparator;
	private ToolBar fToolBar;
	
	private final int fBorderWidth;
	private boolean fHideScrollBars;
	private Listener fShellListener;
	private ListenerList fFocusListeners= new ListenerList(ListenerList.IDENTITY);
	private TextLayout fTextLayout;
	private TextStyle fBoldStyle;

	private BrowserInformationControlInput fInput;

	/**
	 * <code>true</code> iff the browser has completed loading of the last
	 * input set via {@link #setInformation(String)}.
	 * @since 3.4
	 */
	private boolean fCompleted= false;

	/**
	 * The listener to be notified when a delayed location changing event happened.
	 * @since 3.4
	 */
	private IInputChangedListener fDelayedInputChangeListener;

	/**
	 * The listeners to be notified when the input changed.
	 * @since 3.4
	 */
	private ListenerList/*<IInputChangedListener>*/ fInputChangeListeners= new ListenerList(ListenerList.IDENTITY);

	/**
	 * The symbolic name of the font used for size computations, or <code>null</code> to use dialog font.
	 * @since 3.4
	 */
	private final String fSymbolicFontName;
	
	/**
	 * Creates a browser information control with the given shell as parent. The given
	 * information presenter is used to process the information to be displayed. The given
	 * styles are applied to the created browser widget.
	 *
	 * @param parent the parent shell
	 * @param shellStyle the additional styles for the shell
	 * @param style the additional styles for the browser widget
	 */
	public BrowserInformationControl(Shell parent, int shellStyle, int style) {
		this(parent, shellStyle, style, null, null, null);
	}

	/**
	 * Creates a browser information control with the given shell as parent. The given
	 * information presenter is used to process the information to be displayed. The given
	 * styles are applied to the created browser widget.
	 *
	 * @param parent the parent shell
	 * @param shellStyle the additional styles for the shell
	 * @param style the additional styles for the browser widget
	 * @param statusFieldText the text to be used in the optional status field
	 *                         or <code>null</code> if the status field should be hidden
	 */
	public BrowserInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) {
		this(parent, shellStyle, style, null, null, statusFieldText);
	}
	
	/**
	 * Creates a browser information control with the given shell as parent. The given
	 * information presenter is used to process the information to be displayed. The given
	 * styles are applied to the created browser widget.
	 * 
	 * @param parent the parent shell
	 * @param shellStyle the additional styles for the shell
	 * @param style the additional styles for the browser widget
	 * @param symbolicFontName the symbolic name of the font used for size computations
	 * @param statusFieldText the text to be used in the optional status field
	 *            or <code>null</code> if the status field should be hidden
	 * @since 3.4
	 */
	public BrowserInformationControl(Shell parent, int shellStyle, int style, String symbolicFontName, String statusFieldText) {
		this(parent, shellStyle, style, symbolicFontName, null, statusFieldText);
	}
	
	/**
	 * Creates a browser information control with the given shell as parent. The given
	 * information presenter is used to process the information to be displayed. The given
	 * styles are applied to the created browser widget.
	 * 
	 * @param parent the parent shell
	 * @param shellStyle the additional styles for the shell
	 * @param style the additional styles for the browser widget
	 * @param symbolicFontName the symbolic name of the font used for size computations
	 * @param toolBarManager the tool bar manager or <code>null</code> to hide the tool bar
	 * @since 3.4
	 */
	public BrowserInformationControl(Shell parent, int shellStyle, int style, String symbolicFontName, ToolBarManager toolBarManager) {
		this(parent, shellStyle, style, symbolicFontName, toolBarManager, null);
	}
	
	/**
	 * Creates a browser information control with the given shell as parent. The given
	 * information presenter is used to process the information to be displayed. The given
	 * styles are applied to the created browser widget.
	 * <p>
	 * At most one of <code>toolBarManager</code> or <code>statusFieldText</code> can be non-null.
	 * </p>
	 * 
	 * @param parent the parent shell
	 * @param shellStyle the additional styles for the shell
	 * @param style the additional styles for the browser widget
	 * @param symbolicFontName the symbolic name of the font used for size computations
	 * @param toolBarManager the tool bar manager or <code>null</code> to hide the tool bar
	 * @param statusFieldText the text to be used in the optional status field
	 *            or <code>null</code> if the status field should be hidden
	 * @since 3.4
	 */
	private BrowserInformationControl(Shell parent, int shellStyle, int style, String symbolicFontName, ToolBarManager toolBarManager, String statusFieldText) {
		Assert.isLegal(toolBarManager == null || statusFieldText == null);
		fSymbolicFontName= symbolicFontName;
		fToolBarManager= toolBarManager;
		fStatusFieldText= statusFieldText;
		
		fShell= new Shell(parent, SWT.ON_TOP | shellStyle);
		Display display= fShell.getDisplay();

		GridLayout layout= new GridLayout(1, false);
		if ((shellStyle & SWT.NO_TRIM) == 0) {
			fBorderWidth= 0;
		} else {
			fBorderWidth= BORDER;
			fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
		}
		layout.marginHeight= fBorderWidth;
		layout.marginWidth= fBorderWidth;
		fShell.setLayout(layout);
		Composite composite= fShell;
		
		if (statusFieldText != null || toolBarManager != null) {
			composite= new Composite(composite, SWT.NONE);
			layout= new GridLayout(1, false);
			layout.marginHeight= 0;
			layout.marginWidth= 0;
			layout.verticalSpacing= 1;
			layout.horizontalSpacing= 1;
			composite.setLayout(layout);
			
			GridData  gd= new GridData(GridData.FILL_BOTH);
			composite.setLayoutData(gd);
		}
		if (statusFieldText != null) {
			composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
			composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
		}

		createBrowser(composite, style);
		
		if (toolBarManager != null)
			createToolBar(composite, toolBarManager);
		if (statusFieldText != null)
			createStatusField(composite, statusFieldText);

		addDisposeListener(this);
		createTextLayout();
	}

	/**
	 * Creates the browser control.
	 * 
	 * @param composite the parent composite
	 * @param style the additional styles for the browser widget
	 */
	private void createBrowser(Composite composite, int style) {
		fBrowser= new Browser(composite, SWT.NONE);
		fHideScrollBars= (style & SWT.V_SCROLL) == 0 && (style & SWT.H_SCROLL) == 0;
		
		GridData gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
		fBrowser.setLayoutData(gd);
		
		Display display= fShell.getDisplay();
		fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
		fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
		fBrowser.addKeyListener(new KeyListener() {

			public void keyPressed(KeyEvent e)  {
				if (e.character == 0x1B) // ESC
					fShell.dispose(); // XXX: Just hide? Would avoid constant recreations.
			}

			public void keyReleased(KeyEvent e) {}
		});
		/*
		 * XXX revisit when the Browser support is better
		 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=107629 . Choosing a link to a
		 * non-available target will show an error dialog behind the ON_TOP shell that seemingly
		 * blocks the workbench. Disable links completely for now.
		 */
		fBrowser.addLocationListener(new LocationAdapter() {
			/*
			 * @see org.eclipse.swt.browser.LocationAdapter#changing(org.eclipse.swt.browser.LocationEvent)
			 */
			public void changing(LocationEvent event) {
				String location= event.location;
				/*
				 * Using the Browser.setText API triggers a location change to "about:blank".
				 * XXX: remove this code once https://bugs.eclipse.org/bugs/show_bug.cgi?id=130314 is fixed
				 */
				if (!"about:blank".equals(location)) //$NON-NLS-1$
					event.doit= false;
			}
		});

        fBrowser.addProgressListener(new ProgressAdapter() {
            public void completed(ProgressEvent event) {
            	fCompleted= true;
            }
        });
        
		// Replace browser's built-in context menu with none
		fBrowser.setMenu(new Menu(fShell, SWT.NONE));
	}

	/**
	 * Creates the tool bar.
	 * 
	 * @param composite parent
	 * @param toolBarManager manager
	 */
	private void createToolBar(Composite composite, ToolBarManager toolBarManager) {
		fTBSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT);
		fTBSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		final Composite bars= new Composite(composite, SWT.NONE);
		bars.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		
		GridLayout layout= new GridLayout(3, false);
		layout.marginHeight= 0;
		layout.marginWidth= 0;
		layout.horizontalSpacing= 0;
		layout.verticalSpacing= 0;
		bars.setLayout(layout);
		
		fToolBar= toolBarManager.createControl(bars);
		GridData gd= new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false);
		fToolBar.setLayoutData(gd);
		
		Composite spacer= new Composite(bars, SWT.NONE);
		gd= new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.widthHint= 0;
		gd.heightHint= 0;
		spacer.setLayoutData(gd);
		
		addMoveSupport(spacer);
		
		// XXX: workaround for
		// - https://bugs.eclipse.org/bugs/show_bug.cgi?id=219139 : API to add resize grip / grow box in lower right corner of shell
		// - https://bugs.eclipse.org/bugs/show_bug.cgi?id=23980 : platform specific shell resize behavior
		String platform= SWT.getPlatform();
		final boolean isWin= platform.equals("win32"); //$NON-NLS-1$
		if (isWin || platform.equals("gtk")) { //$NON-NLS-1$
			final Canvas resizer= new Canvas(bars, SWT.NONE);
			gd= new GridData(SWT.END, SWT.END, false, true);
			gd.widthHint= fgScrollBarSize.x;
			gd.heightHint= fgScrollBarSize.x;
			resizer.setLayoutData(gd);
			resizer.addPaintListener(new PaintListener() {
				public void paintControl(PaintEvent e) {
					Point s= resizer.getSize();
					int x= s.x - 2;
					int y= s.y - 2;
					int min= Math.min(x, y);
					if (isWin) {
						// draw dots
						e.gc.setBackground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
						int end= min - 1;
						for (int i= 0; i <= 2; i++)
							for (int j= 0; j <= 2 - i; j++)
								e.gc.fillRectangle(end - 4*i, end - 4*j, 2, 2);
						end--;
						e.gc.setBackground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
						for (int i= 0; i <= 2; i++)
							for (int j= 0; j <= 2 - i; j++)
								e.gc.fillRectangle(end - 4*i, end - 4*j, 2, 2);
						
					} else {
						// draw diagonal lines
						e.gc.setForeground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
						for (int i= 1; i < min; i+= 4) {
							e.gc.drawLine(i, y, x, i);
						}
						e.gc.setForeground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
						for (int i= 2; i < min; i+= 4) {
							e.gc.drawLine(i, y, x, i);
						}
					}
				}
			});
			addResizeSupport(resizer);
		}
	}

	/**
	 * Adds support to move the shell by dragging the given control.
	 * 
	 * @param control the control that can be used to move the shell
	 * @since 3.4
	 */
	private void addMoveSupport(final Control control) {
		MouseAdapter moveSupport= new MouseAdapter() {
			private MouseMoveListener fMoveListener;

			public void mouseDown(MouseEvent e) {
				Point shellLoc= fShell.getLocation();
				final int shellX= shellLoc.x;
				final int shellY= shellLoc.y;
				Point mouseLoc= control.toDisplay(e.x, e.y);
				final int mouseX= mouseLoc.x;
				final int mouseY= mouseLoc.y;
				fMoveListener= new MouseMoveListener() {
					public void mouseMove(MouseEvent e2) {
						Point mouseLoc2= control.toDisplay(e2.x, e2.y);
						int dx= mouseLoc2.x - mouseX;
						int dy= mouseLoc2.y - mouseY;
						fShell.setLocation(shellX + dx, shellY + dy);
					}
				};
				control.addMouseMoveListener(fMoveListener);
			}
			
			public void mouseUp(MouseEvent e) {
				control.removeMouseMoveListener(fMoveListener);
				fMoveListener= null;
			}
		};
		control.addMouseListener(moveSupport);
	}
	
	/**
	 * Adds support to resize the shell by dragging the given control.
	 * 
	 * @param control the control that can be used to resize the shell
	 * @since 3.4
	 */
	private void addResizeSupport(final Control control) {
		control.setCursor(new Cursor(control.getDisplay(), SWT.CURSOR_SIZESE));
		MouseAdapter resizeSupport= new MouseAdapter() {
			private MouseMoveListener fResizeListener;
			
			public void mouseDown(MouseEvent e) {
				Point shellSize= fShell.getSize();
				final int shellX= shellSize.x;
				final int shellY= shellSize.y;
				Point mouseLoc= control.toDisplay(e.x, e.y);
				final int mouseX= mouseLoc.x;
				final int mouseY= mouseLoc.y;
				fResizeListener= new MouseMoveListener() {
					public void mouseMove(MouseEvent e2) {
						Point mouseLoc2= control.toDisplay(e2.x, e2.y);
						int dx= mouseLoc2.x - mouseX;
						int dy= mouseLoc2.y - mouseY;
						fBrowser.setRedraw(false);
						try {
							fShell.setSize(shellX + dx, shellY + dy);
						} finally {
							fBrowser.setRedraw(true);
						}
					}
				};
				control.addMouseMoveListener(fResizeListener);
			}
			
			public void mouseUp(MouseEvent e) {
				control.removeMouseMoveListener(fResizeListener);
				fResizeListener= null;
			}
		};
		control.addMouseListener(resizeSupport);
	}

	/**
	 * Creates the status field.
	 * 
	 * @param composite the parent composite
	 * @param statusFieldText the text to show in the status field
	 */
	private void createStatusField(Composite composite, String statusFieldText) {
		fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT);
		fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		// Status field label
		fStatusTextField= new Label(composite, SWT.RIGHT);
		fStatusTextField.setText(statusFieldText);
		Font font= fStatusTextField.getFont();
		FontData[] fontDatas= font.getFontData();
		for (int i= 0; i < fontDatas.length; i++)
			fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
		fStatusTextFont= new Font(fStatusTextField.getDisplay(), fontDatas);
		fStatusTextField.setFont(fStatusTextFont);
		GridData gd= new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
		fStatusTextField.setLayoutData(gd);

		Display display= fShell.getDisplay();
		fStatusTextField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
		fStatusTextField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
	}

	/**
	 * {@inheritDoc}
	 * @deprecated use {@link #setInput(Object)}
	 */
	public void setInformation(final String content) {
		setInput(new BrowserInformationControlInput(null) {
			public String getHtml() {
				return content;
			}
		});
	}
	
	/**
	 * {@inheritDoc} This control can handle {@link String} and
	 * {@link BrowserInformationControlInput}.
	 */
	public void setInput(Object input) {
		Assert.isLegal(input == null || input instanceof String || input instanceof BrowserInformationControlInput);

		if (input instanceof String) {
			setInformation((String)input);
			return;
		}

		fInput= (BrowserInformationControlInput)input;
		
		String content= null;
		if (fInput != null)
			content= fInput.getHtml();
		
		fBrowserHasContent= content != null && content.length() > 0;

		if (!fBrowserHasContent)
			content= "<html><body ></html>"; //$NON-NLS-1$

		int shellStyle= fShell.getStyle();
		boolean RTL= (shellStyle & SWT.RIGHT_TO_LEFT) != 0;

		// The default "overflow:auto" would not result in a predictable width for the client area
		// and the re-wrapping would cause visual noise
		String[] styles= null;
		if (RTL && !fHideScrollBars)
			styles= new String[] { "direction:rtl;", "overflow:scroll;", "word-wrap:break-word;" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		else if (RTL && fHideScrollBars)
			styles= new String[] { "direction:rtl;", "overflow:hidden;", "word-wrap:break-word;" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		else if (fHideScrollBars)
			//XXX: In IE, "word-wrap: break-word;" causes bogus wrapping even in non-broken words :-(see e.g. Javadoc of String).
			// Re-check whether we really still need this now that the Javadoc Hover header already sets this style.
			styles= new String[] { "overflow:hidden;"/*, "word-wrap: break-word;"*/ }; //$NON-NLS-1$
		else
			styles= new String[] { "overflow:scroll;" }; //$NON-NLS-1$
		
		StringBuffer buffer= new StringBuffer(content);
		HTMLPrinter.insertStyles(buffer, styles);
		content= buffer.toString();
		
		/*
		 * XXX: Should add some JavaScript here that shows something like
		 * "(continued...)" or "..." at the end of the visible area when the page overflowed
		 * with "overflow:hidden;".
		 */
		
		fCompleted= false;
		fBrowser.setText(content);
		
		Object[] listeners= fInputChangeListeners.getListeners();
		for (int i= 0; i < listeners.length; i++)
			((IInputChangedListener)listeners[i]).inputChanged(fInput);
	}

	/*
	 * @see org.eclipse.jdt.internal.ui.text.IInformationControlExtension4#setStatusText(java.lang.String)
	 * @since 3.2
	 */
	public void setStatusText(String statusFieldText) {
		fStatusFieldText= statusFieldText;
	}

	/*
	 * @see IInformationControl#setVisible(boolean)
	 */
	public void setVisible(boolean visible) {
		if (fShell.isVisible() == visible)
			return;
		
		if (visible) {
			if (fStatusTextField != null) {
				boolean state= fStatusFieldText != null;
				if (state)
					fStatusTextField.setText(fStatusFieldText);
				fStatusTextField.setVisible(state);
				fSeparator.setVisible(state);
			}
		}

		if (!visible) {
			fShell.setVisible(false);
			setInput(null);
			return;
		}
		
		/*
		 * The Browser widget flickers when made visible while it is not completely loaded.
		 * The fix is to delay the call to setVisible until either loading is completed
		 * (see ProgressListener in constructor), or a timeout has been reached.
		 */
		final Display display= fShell.getDisplay();
        
        // Make sure the display wakes from sleep after timeout:
        display.timerExec(100, new Runnable() {
            public void run() {
                fCompleted= true;
            }
        });
        
		while (!fCompleted) {
			// Drive the event loop to process the events required to load the browser widget's contents:
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		
		if (fShell == null || fShell.isDisposed())
			return;
		
		/*
		 * Avoids flickering when replacing hovers, especially on Vista in ON_CLICK mode.
		 * Causes flickering on GTK. Carbon does not care.
		 */
		if ("win32".equals(SWT.getPlatform())) //$NON-NLS-1$
			fShell.moveAbove(null);
		
        fShell.setVisible(true);
	}

	/**
	 * Creates and initializes the text layout used
	 * to compute the size hint.
	 * 
	 * @since 3.2
	 */
	private void createTextLayout() {
		fTextLayout= new TextLayout(fBrowser.getDisplay());
		
		// Initialize fonts
		Font font= fSymbolicFontName == null ? JFaceResources.getDialogFont() : JFaceResources.getFont(fSymbolicFontName);
		fTextLayout.setFont(font);
		fTextLayout.setWidth(-1);
		FontData[] fontData= font.getFontData();
		for (int i= 0; i < fontData.length; i++)
			fontData[i].setStyle(SWT.BOLD);
		font= new Font(fShell.getDisplay(), fontData);
		fBoldStyle= new TextStyle(font, null, null);
		
		// Compute and set tab width
		fTextLayout.setText("    "); //$NON-NLS-1$
		int tabWidth = fTextLayout.getBounds().width;
		fTextLayout.setTabs(new int[] {tabWidth});

		fTextLayout.setText(""); //$NON-NLS-1$
	}

	/*
	 * @see IInformationControl#dispose()
	 */
	public void dispose() {
		if (fTextLayout != null)
			fTextLayout.dispose();
		fTextLayout= null;
		if (fBoldStyle != null)
			fBoldStyle.font.dispose();
		fBoldStyle= null;
		if (fToolBarManager != null)
			fToolBarManager.dispose();
		if (fShell != null && !fShell.isDisposed())
			fShell.dispose();
		else
			widgetDisposed(null);
	}

	/*
	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
	 */
	public void widgetDisposed(DisposeEvent event) {
		if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
			fStatusTextFont.dispose();

		fShell= null;
		fBrowser= null;
		fStatusTextFont= null;
	}

	/*
	 * @see IInformationControl#setSize(int, int)
	 */
	public void setSize(int width, int height) {
		fShell.setSize(width, height);
	}

	/*
	 * @see IInformationControl#setLocation(Point)
	 */
	public void setLocation(Point location) {
		fShell.setLocation(location);
	}

	/*
	 * @see IInformationControl#setSizeConstraints(int, int)
	 */
	public void setSizeConstraints(int maxWidth, int maxHeight) {
		fMaxWidth= maxWidth;
		fMaxHeight= maxHeight;
	}

	/*
	 * @see IInformationControl#computeSizeHint()
	 */
	public Point computeSizeHint() {
		Rectangle trim= computeTrim();
		int height= trim.height;
		
		//FIXME: The HTML2TextReader does not render <p> like a browser.
		// Instead of inserting an empty line, it just adds a single line break.
		// Furthermore, the indentation of <dl><dd> elements is too small (e.g with a long @see line)
		TextPresentation presentation= new TextPresentation();
		HTML2TextReader reader= new HTML2TextReader(new StringReader(fInput.getHtml()), presentation);
		String text;
		try {
			text= reader.getString();
		} catch (IOException e) {
			text= ""; //$NON-NLS-1$
		}

		fTextLayout.setText(text);
		fTextLayout.setWidth(fMaxWidth - trim.width);
		Iterator iter= presentation.getAllStyleRangeIterator();
		while (iter.hasNext()) {
			StyleRange sr= (StyleRange)iter.next();
			if (sr.fontStyle == SWT.BOLD)
				fTextLayout.setStyle(fBoldStyle, sr.start, sr.start + sr.length - 1);
		}
		
		Rectangle bounds= fTextLayout.getBounds(); // does not return minimum width, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=217446
		int lineCount= fTextLayout.getLineCount();
		int textWidth= 0;
		for (int i= 0; i < lineCount; i++) {
			Rectangle rect= fTextLayout.getLineBounds(i);
			textWidth= Math.max(textWidth, rect.x + rect.width);
		}
		bounds.width= textWidth;
		fTextLayout.setText(""); //$NON-NLS-1$
		
		int minWidth= bounds.width;
		height= height + bounds.height;
		
		// Add some air to accommodate for different browser renderings
		minWidth+= 15;
		height+= 15;

		// Consider width of text field and toolbar (height is already in trim)
		if (fStatusFieldText != null && fSeparator != null) {
			Point statusTextSize= fStatusTextField.computeSize(SWT.DEFAULT, SWT.DEFAULT);
			minWidth= Math.max(minWidth, statusTextSize.x);
		}
		if (fToolBar != null && fTBSeparator != null) {
			Point toolBarSize= fToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
			minWidth= Math.max(minWidth, toolBarSize.x);
		}
		
		// Apply max size constraints
		if (fMaxWidth != SWT.DEFAULT)
			minWidth= Math.min(fMaxWidth, minWidth + trim.width);
		if (fMaxHeight != SWT.DEFAULT)
			height= Math.min(fMaxHeight, height);

		// Ensure minimal size
		int width= Math.max(MIN_WIDTH, minWidth);
		height= Math.max(MIN_HEIGHT, height);
		
		return new Point(width, height);
	}

	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim()
	 */
	public Rectangle computeTrim() {
		Rectangle trim= fShell.computeTrim(0, 0, 0, 0);
		addInternalTrim(trim);
		return trim;
	}

	/**
	 * Adds the internal trimmings to the given trim of the shell.
	 * 
	 * @param trim the shell's trim, will be updated
	 * @since 3.4
	 */
	private void addInternalTrim(Rectangle trim) {
		trim.x-= fBorderWidth;
		trim.y-= fBorderWidth;
		trim.width+= 2 * fBorderWidth;
		trim.height+= 2 * fBorderWidth;
		
		if (! fHideScrollBars) {
			boolean RTL= (fShell.getStyle() & SWT.RIGHT_TO_LEFT) != 0;
			if (RTL) {
				trim.x-= fgScrollBarSize.x;
			}
			trim.width+= fgScrollBarSize.x;
			trim.height+= fgScrollBarSize.y;
		}
		
		if (fStatusTextField != null) {
			trim.height+= 2; // from the layout's verticalSpacing
			trim.height+= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
			trim.height+= fStatusTextField.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
		}
		
		if (fToolBar != null) {
			trim.height+= 2; // from the layout's verticalSpacing
			trim.height+= fTBSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
			trim.height+= fToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
		}
	}
	
	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension3#getBounds()
	 */
	public Rectangle getBounds() {
		return fShell.getBounds();
	}

	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation()
	 */
	public boolean restoresLocation() {
		return false;
	}

	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize()
	 */
	public boolean restoresSize() {
		return false;
	}

	/*
	 * @see IInformationControl#addDisposeListener(DisposeListener)
	 */
	public void addDisposeListener(DisposeListener listener) {
		fShell.addDisposeListener(listener);
	}

	/*
	 * @see IInformationControl#removeDisposeListener(DisposeListener)
	 */
	public void removeDisposeListener(DisposeListener listener) {
		fShell.removeDisposeListener(listener);
	}
	
	/**
	 * Adds the listener to the collection of listeners who will be
	 * notified when the current location has changed or is about to change.
	 * 
	 * @param listener the location listener
	 * @since 3.4
	 */
	public void addLocationListener(LocationListener listener) {
		fBrowser.addLocationListener(listener);
	}

	/*
	 * @see IInformationControl#setForegroundColor(Color)
	 */
	public void setForegroundColor(Color foreground) {
		fBrowser.setForeground(foreground);
	}

	/*
	 * @see IInformationControl#setBackgroundColor(Color)
	 */
	public void setBackgroundColor(Color background) {
		fBrowser.setBackground(background);
	}

	/*
	 * @see IInformationControl#isFocusControl()
	 */
	public boolean isFocusControl() {
		return fShell.getDisplay().getActiveShell() == fShell;
	}

	/*
	 * @see IInformationControl#setFocus()
	 */
	public void setFocus() {
		fShell.forceFocus();
		fBrowser.setFocus();
	}

	/*
	 * @see IInformationControl#addFocusListener(FocusListener)
	 */
	public void addFocusListener(final FocusListener listener) {
		if (fFocusListeners.isEmpty()) {
			fShellListener=  new Listener() {
				public void handleEvent(Event event) {
					Object[] listeners= fFocusListeners.getListeners();
					for (int i = 0; i < listeners.length; i++) {
						FocusListener focusListener= (FocusListener)listeners[i];
						if (event.type == SWT.Activate) {
							focusListener.focusGained(new FocusEvent(event));
						} else {
							focusListener.focusLost(new FocusEvent(event));
						}
					}
				}
			};
			fBrowser.getShell().addListener(SWT.Deactivate, fShellListener);
			fBrowser.getShell().addListener(SWT.Activate, fShellListener);
		}
		fFocusListeners.add(listener);
	}

	/*
	 * @see IInformationControl#removeFocusListener(FocusListener)
	 */
	public void removeFocusListener(FocusListener listener) {
		fFocusListeners.remove(listener);
		if (fFocusListeners.isEmpty()) {
			fBrowser.getShell().removeListener(SWT.Activate, fShellListener);
			fBrowser.getShell().removeListener(SWT.Deactivate, fShellListener);
			fShellListener= null;
		}
	}

	/*
	 * @see IInformationControlExtension#hasContents()
	 */
	public boolean hasContents() {
		return fBrowserHasContent;
	}
	
	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension5#containsControl(org.eclipse.swt.widgets.Control)
	 * @since 3.4
	 */
	public boolean containsControl(Control control) {
		do {
			if (control == fShell)
				return true;
			if (control instanceof Shell)
				return false;
			control= control.getParent();
		} while (control != null);
		return false;
	}
	
	/**
	 * Adds a listener for input changes to this input change provider.
	 * Has no effect if an identical listener is already registered.
	 * 
	 * @param inputChangeListener the listener to add
	 * @since 3.4
	 */
	public void addInputChangeListener(IInputChangedListener inputChangeListener) {
		Assert.isNotNull(inputChangeListener);
		fInputChangeListeners.add(inputChangeListener);
	}
	
	/**
	 * Removes the given input change listener from this input change provider.
	 * Has no effect if an identical listener is not registered.
	 * 
	 * @param inputChangeListener the listener to remove
	 * @since 3.4
	 */
	public void removeInputChangeListener(IInputChangedListener inputChangeListener) {
		fInputChangeListeners.remove(inputChangeListener);
	}
	
	/*
	 * @see org.eclipse.jface.text.IDelayedInputChangeProvider#setDelayedInputChangeListener(org.eclipse.jface.text.IInputChangedListener)
	 * @since 3.4
	 */
	public void setDelayedInputChangeListener(IInputChangedListener inputChangeListener) {
		fDelayedInputChangeListener= inputChangeListener;
	}
	
	/**
	 * Tells whether a delayed input change listener is registered.
	 * 
	 * @return <code>true</code> iff a delayed input change
	 *         listener is currently registered
	 * @since 3.4
	 */
	public boolean hasDelayedInputChangeListener() {
		return fDelayedInputChangeListener != null;
	}
	
	/**
	 * Notifies listeners of a delayed input change.
	 * 
	 * @param newInput the new input, or <code>null</code> to request cancellation
	 * @since 3.4
	 */
	public void notifyDelayedInputChange(Object newInput) {
		if (fDelayedInputChangeListener != null)
			fDelayedInputChangeListener.inputChanged(newInput);
	}
	
	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension5#isVisible()
	 * @since 3.4
	 */
	public boolean isVisible() {
		return fShell != null && ! fShell.isDisposed() && fShell.isVisible();
	}
	
	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension5#allowMoveIntoControl()
	 * @since 3.4
	 */
	public boolean allowMoveIntoControl() {
		return true;
	}
	
	/*
	 * @see java.lang.Object#toString()
	 * @since 3.4
	 */
	public String toString() {
		String style= (fShell.getStyle() & SWT.RESIZE) == 0 ? "fixed" : "resizeable"; //$NON-NLS-1$ //$NON-NLS-2$
		return super.toString() + " -  style: " + style; //$NON-NLS-1$
	}

	/**
	 * @return the current browser input or <code>null</code>
	 */
	public BrowserInformationControlInput getInput() {
		return fInput;
	}
	
	/*
	 * @see org.eclipse.jface.text.IInformationControlExtension5#computeSizeConstraints(int, int)
	 */
	public Point computeSizeConstraints(int widthInChars, int heightInChars) {
		if (fSymbolicFontName == null)
			return null;
		
		GC gc= new GC(fBrowser);
		Font font= fSymbolicFontName == null ? JFaceResources.getDialogFont() : JFaceResources.getFont(fSymbolicFontName);
		gc.setFont(font);
		int width= gc.getFontMetrics().getAverageCharWidth();
		int height = gc.getFontMetrics().getHeight();
		gc.dispose();

		return new Point (widthInChars * width, heightInChars * height);
	}

}
