package name.abuchen.portfolio.ui.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Scanner;
import java.util.function.Consumer;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.osgi.framework.Bundle;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.PortfolioPlugin;
import name.abuchen.portfolio.util.TokenReplacingReader;
public class EmbeddedBrowser
{
private final String htmlpage;
private Browser browser;
public EmbeddedBrowser(String htmlpage)
{
this.htmlpage = htmlpage;
}
public Control createControl(Composite parent, Consumer<Browser> functions)
{
Composite container = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(container);
try
{
browser = new Browser(container, SWT.NONE);
browser.setJavascriptEnabled(true);
GridDataFactory.fillDefaults().grab(true, true).applyTo(browser);
if (functions != null)
functions.accept(browser);
browser.setText(loadHTML(htmlpage));
Menu menu = new Menu(browser);
browser.setMenu(menu);
}
catch (SWTError e)
{
// if creation of embedded browser fails, provide some hints
PortfolioPlugin.log(e);
String stacktrace = ExceptionUtils.getStackTrace(e);
Text text = new Text(container, SWT.WRAP);
GridDataFactory.fillDefaults().grab(true, true).applyTo(text);
text.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
text.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_RED));
text.setText(MessageFormat.format(Messages.MsgEmbeddedBrowserError, stacktrace));
}
return container;
}
public void refresh()
{
browser.setText(loadHTML(htmlpage));
}
private String loadHTML(String htmlpage)
{
try (InputStream h = FileLocator.openStream(PortfolioPlugin.getDefault().getBundle(), //
new Path(htmlpage), false);
Scanner s = new Scanner(new TokenReplacingReader(
new InputStreamReader(h, StandardCharsets.UTF_8), new PathResolver())))
{
return s.useDelimiter("\\Z").next(); //$NON-NLS-1$
}
catch (IOException e)
{
PortfolioPlugin.log(e);
return "<html><body><h1>Error: " + e.getMessage() + "</h1></body></html>"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
private static final class PathResolver implements TokenReplacingReader.ITokenResolver
{
private Bundle bundle = PortfolioPlugin.getDefault().getBundle();
@Override
public String resolveToken(String tokenName)
{
try
{
URL fileURL = FileLocator.toFileURL(bundle.getEntry(tokenName));
return Platform.OS_WIN32.equals(Platform.getOS()) ? fileURL.getPath().substring(1) : fileURL.getPath();
}
catch (NullPointerException | IOException e)
{
PortfolioPlugin.log(e);
return tokenName;
}
}
}
}