package com.redhat.ceylon.eclipse.util; import static org.eclipse.jface.text.TextPresentation.applyTextPresentation; import org.eclipse.jface.text.TextPresentation; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.LocationListener; import org.eclipse.swt.browser.OpenWindowListener; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.browser.VisibilityWindowListener; import org.eclipse.swt.browser.WindowEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Drawable; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import com.redhat.ceylon.eclipse.code.html.HTMLTextPresenter; import com.redhat.ceylon.eclipse.ui.CeylonPlugin; public class DocBrowser { private TextPresentation presentation = new TextPresentation(); private Browser browser; private StyledText styledText; private String text; private boolean visible; private ProgressListener progressListener; public boolean isVisible() { return visible; } public void setVisible(boolean visible) { this.visible = visible; if (browser!=null) { browser.setVisible(visible); } if (styledText!=null) { styledText.setVisible(visible); } } public void addLocationListener(LocationListener listener) { if (browser!=null) { browser.addLocationListener(listener); } } public void setText(String text) { if (text!=null) { if (this.text==null || !text.equals(this.text)) { this.text = text; internalSetText(text); } } if (progressListener!=null && styledText!=null) { progressListener.completed( new ProgressEvent(styledText)); } } private void internalSetText(String text) { if (browser!=null) { browser.setText(text); } if (styledText!=null) { presentation.clear(); Rectangle area = styledText.getClientArea(); String content = new HTMLTextPresenter() //TODO: should be new HTMLTextPresenter(false) but that's crashing SWT for some reason .updatePresentation(styledText, text, presentation, area.width-2, Integer.MAX_VALUE); styledText.setText(content); applyTextPresentation(presentation, styledText); } } public DocBrowser(Composite parent, int style) { Display display = parent.getDisplay(); Color fg = display.getSystemColor(SWT.COLOR_INFO_FOREGROUND); Color bg = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND); Font font = CeylonPlugin.getHoverFont(); if (isAvailable(parent)) { browser = new Browser(parent, style); browser.setJavascriptEnabled(false); browser.setForeground(fg); browser.setBackground(bg); browser.setFont(font); if (parent.getLayout() instanceof GridLayout) { browser.setLayoutData( new GridData(GridData.FILL_BOTH)); } browser.addOpenWindowListener( new OpenWindowListener() { @Override public void open(WindowEvent event) { event.required = true; //Cancel opening of new windows } }); } else { styledText = new StyledText(parent, SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | style); styledText.setForeground(fg); styledText.setBackground(bg); if (parent.getLayout() instanceof GridLayout) { styledText.setLayoutData( new GridData(GridData.FILL_BOTH)); } styledText.setFont(font); styledText.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { internalSetText(text); } }); } } private static Boolean available; private static boolean isAvailable(Composite parent) { if (available==null) { try { Browser browser = new Browser(parent, SWT.NONE); browser.dispose(); available = true; } catch (SWTError e) { available = false; } } return available.booleanValue(); } public void close() { if (browser!=null) browser.close(); } public void setMenu(Menu menu) { if (browser!=null) { browser.setMenu(menu); } if (styledText!=null) { styledText.setMenu(menu); } } public void addVisibilityWindowListener( final VisibilityWindowListener listener) { if (browser!=null) { browser.addVisibilityWindowListener(listener); } if (styledText!=null) { styledText.addListener(SWT.Show, new Listener() { @Override public void handleEvent(Event event) { listener.show(new WindowEvent(styledText)); } }); styledText.addListener(SWT.Hide, new Listener() { @Override public void handleEvent(Event event) { listener.hide(new WindowEvent(styledText)); } }); } } public void setProgressListener(ProgressListener listener) { this.progressListener = listener; if (browser!=null) { browser.addProgressListener(listener); } } public void setRedraw(boolean b) { if (browser!=null) { browser.setRedraw(b); } if (styledText!=null) { styledText.setRedraw(b); } } public Device getDisplay() { if (browser!=null) { return browser.getDisplay(); } if (styledText!=null) { return styledText.getDisplay(); } return null; } public Drawable getDrawable() { if (browser!=null) { return browser; } if (styledText!=null) { return styledText; } return null; } public void setForeground(Color foreground) { if (browser!=null) { browser.setForeground(foreground); } if (styledText!=null) { styledText.setForeground(foreground); } } public void setBackground(Color background) { if (browser!=null) { browser.setBackground(background); } if (styledText!=null) { styledText.setBackground(background); } } }