3 classvar <>defaultHomeUrl;
4 classvar <>openNewWindows = false;
16 NotificationCenter.register(SCDoc, \docMapDidUpdate, this) {
17 if(WebView.implClass.respondsTo(\clearCache)) {
25 if( singleton.isNil ) {
27 singleton.window.onClose = {
35 *new { arg aHomeUrl, newWin;
36 if( aHomeUrl.isNil ) {
37 aHomeUrl = defaultHomeUrl ?? { SCDoc.helpTargetDir ++ "/Help.html" };
39 ^super.new.init( aHomeUrl, newWin ?? { openNewWindows } );
43 if(openNewWindows,{this.new},{this.instance}).goTo(url);
46 *openBrowsePage {|category|
47 category = if(category.notNil) {"#"++category} {""};
48 this.goTo(SCDoc.helpTargetDir++"/Browse.html"++category);
50 *openSearchPage {|text|
51 text = if(text.notNil) {"#"++text} {""};
52 this.goTo(SCDoc.helpTargetDir++"/Search.html"++text);
55 this.goTo(SCDoc.findHelpFile(text));
57 *openHelpForMethod {|method|
58 var cls = method.ownerClass;
59 var met = method.name.asString;
61 cls = cls.name.asString.drop(5);
64 cls = cls.name.asString;
67 this.goTo(Help.dir+/+"Classes"+/+cls++".html#"++met);
71 ^("file://" ++ SCDoc.helpTargetDir +/+ "OldHelpWrapper.html#"++url++"?"++
72 SCDoc.helpTargetDir +/+ if((c=url.basename.split($.).first).asSymbol.asClass.notNil)
73 {"Classes" +/+ c ++ ".html"}
74 {"Guides/WritingHelp.html"})
76 cmdPeriod { rout.play(AppClock) }
77 goTo {|url, brokenAction|
78 var newPath, oldPath, plainTextExts = #[".sc",".scd",".txt",".schelp"];
80 //FIXME: since multiple scdoc queries can be running at the same time,
81 //it would be best to create a queue and run them in order, but only use the url from the last.
85 ^this.openTextFile(url);
92 brokenAction = brokenAction ? {SCDoc.helpTargetDir++"/BrokenLink.html#"++url};
96 url = SCDoc.prepareHelpForURL(url) ?? brokenAction;
97 #newPath, oldPath = [url,webView.url].collect {|x|
98 if(x.notEmpty) {x.findRegexp("(^\\w+://)?([^#]+)(#.*)?")[1..].flop[1][1]}
100 // detect old helpfiles and open them in OldHelpWrapper
101 if(block{|break| Help.do {|key,path| if(url.endsWith(path)) {break.value(true)}}; false}) {
102 url = HelpBrowser.getOldWrapUrl(url)
105 // needed since onLoadFinished is not called if the path did not change:
106 if(newPath == oldPath) {webView.onLoadFinished.value};
109 webView.html = err.errorString;
112 CmdPeriod.remove(this);
118 goHome { this.goTo(homeUrl); }
120 goBack { webView.back; }
122 goForward { webView.forward; }
124 /* ------------------------------ private ------------------------------ */
126 init { arg aHomeUrl, aNewWin;
128 var lblFind, txtFind, findView, saveSize, toggleFind;
129 var strh = "Tj".bounds.height;
130 var vPad = 10, hPad = 20;
138 winRect = Rect(0, 0, 800, (Window.screenBounds.height * 0.8).floor);
139 winRect = winRect.moveToPoint(winRect.centerIn(Window.screenBounds));
141 window = Window.new( bounds: winRect ).name_("SuperCollider Help");
147 [[\Back,"<"], [\Forward,">"], [\Reload, "Reload"]].do { |item|
149 var w = str.bounds.width + hPad;
150 toolbar[item[0]] = Button( window, Rect(x,y,w,h) ).states_([[str]]);
155 str = "Quick lookup:";
156 w = str.bounds.width + 5;
157 StaticText(window, Rect(x,y,w,h)).string_(str);
160 srchBox = TextField.new( window, Rect(x,y,w,h) ).resize_(1);
161 if(GUI.current.id == \qt) {
162 srchBox.toolTip = "Smart quick help lookup. Prefix with # to just search.";
164 srchBox.action = {|x|
165 if(x.string.notEmpty) {
166 this.goTo(if(x.string.first==$#)
167 {SCDoc.helpTargetDir++"/Search.html#"++x.string.drop(1)}
168 {SCDoc.findHelpFile(x.string)}
173 openNewWin = aNewWin;
175 if(GUI.current.respondsTo(\checkBox)) {
176 str = "Open links in new window";
177 w = str.bounds.width + 50;
178 CheckBox.new (window, Rect(x, y, w, h) )
182 .action_({ |b| openNewWin = b.value });
184 str = "Open links in same window";
185 w = str.bounds.width + 5;
186 Button.new( window, Rect(x, y, w, h) )
188 .states_([[str],["Open links in new window"]])
189 .value_(openNewWin.asInteger)
190 .action_({ |b| openNewWin = b.value.asBoolean });
196 findView = CompositeView(window, Rect(x,y,w,h+10)).visible_(false).resize_(2);
199 x = winRect.width - marg - w;
200 txtFind = TextField.new( findView, Rect(x,y,w,h) ).resize_(3);
201 str = "Find text in document:";
202 w = str.bounds.width + 5;
204 lblFind = StaticText.new( findView, Rect(x, y, w, h) )
210 w = winRect.width - 10;
211 h = winRect.height - y - marg;
212 webView = WebView.new( window, Rect(x,y,w,h) ).resize_(5);
213 webView.html = "Please wait while initializing Help... (This might take several seconds the first time)";
215 if(webView.respondsTo(\setFontFamily)) {
216 webView.setFontFamily(\fixed, Platform.case(
218 \linux, { "Andale Mono" },
223 webView.onLoadFinished = {
225 window.name = "SuperCollider Help: %".format(webView.title);
227 webView.onLoadFailed = { this.stopAnim };
228 webView.onLinkActivated = {|wv, url|
229 var newPath, oldPath;
231 #newPath, oldPath = [url,webView.url].collect {|x|
232 if(x.notEmpty) {x.findRegexp("(^\\w+://)?([^#]+)(#.*)?")[1..].flop[1][1]}
235 if(newPath!=oldPath) {
236 HelpBrowser.new(newWin:true).goTo(url);
241 if(webView.respondsTo(\onReload_)) {
242 webView.onReload = {|wv, url|
248 if(findView.visible.not) {
249 saveSize = webView.bounds;
250 h = findView.bounds.height + marg;
251 webView.bounds = Rect(saveSize.left,saveSize.top+h,saveSize.width,saveSize.height-h);
252 findView.visible = true;
255 webView.bounds = saveSize;
256 findView.visible = false;
260 webView.enterInterpretsSelection = true;
261 webView.keyDownAction = { arg view, char, mods;
262 if( (char.ascii == 13) && (mods.isCtrl || mods.isCmd || mods.isShift) ) {
263 view.tryPerform(\evaluateJavaScript,"selectLine()");
266 window.view.keyDownAction = { arg view, char, mods;
267 if( ((char.ascii == 6) && mods.isCtrl) || (char == $f && mods.isCmd) ) {
271 if(findView.visible) {toggleFind.value};
275 toolbar[\Back].action = { this.goBack };
276 toolbar[\Forward].action = { this.goForward };
277 toolbar[\Reload].action = { this.goTo( webView.url ) };
278 txtFind.action = { |x| webView.findText( x.string ); };
282 var win, winRect, txt, file, fonts;
283 path = path.replace("%20"," ").findRegexp("(^\\w+://)?([^#]+)(#.*)?")[1..].flop[1][1];
284 if(File.exists(path)) {
287 webView.url = SCDoc.helpTargetDir++"/BrokenLink.html#"++path;
293 var progress = [">---","->--","-->-","--->"];
294 animCount = animCount + 1;
300 window.name = ("Loading"+p);
302 if(animCount==0) {break.value};
306 // lblStatus.string_("");
312 animCount = animCount - 1;
320 HelpBrowser.instance.goHome;