using gfx::Border
using fwt::BorderPane
using fwt::Desktop
using fwt::Event
using fwt::WebBrowser
using flux::View
using flux::FileResource
using fandoc::FandocParser
using compilerDoc::Doc
using compilerDoc::DocRenderer
** A View with a Web Browser to show html, fandocs and files. All browser navigation is saved in
** the flux history.
**
** If like me, you're in the habit of hitting F5 to refresh the contents of a browser, you'll want
** to bind the 'Reload View' command with F5. Here's how.
**
** Create or open up '%FAN_HOME%/etc/flux/locale/en.props' and remove any reference to F5 to disassociate it
** from the Find command. e.g. change it to
**
** find.name=Find
** find.accelerator=
**
** Then edit '%FAN_HOME%/etc/flux/keys.fog' to add the new command binding:
**
** "refresh": "F5"
**
** Note: Only tested on Win7 64bit - Web Browser stability on other platforms is unassured!
class Browser : View {
private static const Log log := Browser#.pod.log
private WebBrowser? browser
override Void onLoad() {
browser = WebBrowser() {
it.onHyperlink.add |e| { this.onHyperlink(e) }
}
content = BorderPane {
it.content = browser
it.border = Border("0,0,0,1 $Desktop.sysNormShadow")
}
// see http://fantom.org/sidewalk/topic/2024#c13355
Desktop.callLater(100ms) |->| {
browser.focus
}
}
override Void onActive() {
if (resource is FandocResource) {
log.info(" - displaying Fandoc -> $resource.uri")
fanRes := resource as FandocResource
browser.loadStr(fanRes.toHtml)
// TODO: How can you load an anchor?
// if (resource.uri.frag != null)
// browser.load(`#${resource.uri.frag}`) // -> displaying web http:///#line205
// browser.load(`about:#${resource.uri.frag}`) // -> JVM Crash
// browser.load(`about:blank#${resource.uri.frag}`) // -> displaying fandoc src-Variant.fan
// browser.load(`blank#${resource.uri.frag}`) // -> JVM Crash
}
if (resource is InternetResource) {
log.info(" - displaying Internet -> $resource.uri")
// see http://fantom.org/sidewalk/topic/2069
browser.load(resource.uri.plusQuery(["dodgyLink":"true"]))
}
if (resource is FileResource) {
log.info(" - displaying File -> $resource.uri")
file := (resource as FileResource).file
fandoc := file.readAllStr
html := fandocToHtml(fandoc, resource.uri)
browser.loadStr(html)
}
}
private Void onHyperlink(Event event) {
// don't hyperlink in place, instead we route the hyperlink through the flux frame to save
// the uri in the history and give consistent navigation
Uri uri := event.data
// stop an infinite loop and return early
// see http://fantom.org/sidewalk/topic/2069
if (uri.query.containsKey("dodgyLink"))
return
// ignore links to anchors on the same page (IE defines these links as "about:blank#anchor")
if (uri.scheme == "about" && uri.name == "blank")
return
// anything beyond this point will have its uri resolved and routed through `Frame.load`
// so cancel the link event in the browser
event.data = null
// IE gives relative links the scheme 'about' so strip it off and return an absolute URI,
// using the existing resource as the base
if (uri.scheme == "about" && !uri.isPathAbs)
uri = `${resource.uri.parent}${uri.pathStr}`
// route the URI through flux so it gets stored in the history
frame.load(uri)
}
** internal for testing
internal static Str fandocToHtml(Str fandoc, Uri? base := null) {
writer := FandocWriter.fromNew(base)
doc := FandocParser().parseStr(fandoc)
doc.write(writer)
return writer.toHtml
}
}