// Since SC v3.2 dev, Document is an ABSTRACT class. Can't be instantiated directly. // Subclasses provide the editor-specific implementation, e.g. CocoaDocument for the standard Mac interface. // Subclasses also (in their SC code files) add a "implementationClass" method to Document to tell it to use them. Document { classvar current; classvar initAction; classvar <>autoRun = true; classvar <>implementationClass; //don't change the order of these vars: var keyDownAction, <>keyUpAction, <>mouseUpAction; var <>toFrontAction, <>endFrontAction, <>onClose, <>mouseDownAction; var = 0 } } { start = start - 1 }; while { str[end] !== Char.nl and: { end < max } } { end = end + 1 }; ^str.copyRange(start + 1, end); } //actions: didBecomeKey { this.class.current = this; this.saveCurrentEnvironment; toFrontAction.value(this); } didResignKey { endFrontAction.value(this); this.restoreCurrentEnvironment; } mouseUp{ | x, y, modifiers, buttonNumber, clickCount, clickPos | mouseUpAction.value(this, x, y, modifiers, buttonNumber, clickCount) } keyDown { | character, modifiers, unicode, keycode | this.class.globalKeyDownAction.value(this,character, modifiers, unicode, keycode); keyDownAction.value(this,character, modifiers, unicode, keycode); } keyUp { | character, modifiers, unicode, keycode | this.class.globalKeyUpAction.value(this,character, modifiers, unicode, keycode); keyUpAction.value(this,character, modifiers, unicode, keycode); } == { | doc | ^if(this.path.isNil or: { doc.path.isNil }) { doc === this } { this.path == doc.path } } hash { ^(this.path ? this).hash } *defaultUsesAutoInOutdent_ {|bool| Document.implementationClass.prDefaultUsesAutoInOutdent_(bool) } usesAutoInOutdent_ {|bool| this.prUsesAutoInOutdent_(bool) } *prDefaultUsesAutoInOutdent_{|bool| this.subclassResponsibility(thisMethod); } *prPostColor_{ |color| this.subclassResponsibility(thisMethod); } prUsesAutoInOutdent_{|bool| ^this.subclassResponsibility(thisMethod); } // private implementation prIsEditable_{ | editable=true | ^this.subclassResponsibility(thisMethod) } prSetTitle { | argName | ^this.subclassResponsibility(thisMethod) } prGetTitle { ^this.subclassResponsibility(thisMethod) } prGetFileName { ^this.subclassResponsibility(thisMethod) } prSetFileName { | apath | ^this.subclassResponsibility(thisMethod) } prGetBounds { | argBounds | ^this.subclassResponsibility(thisMethod) } prSetBounds { | argBounds | ^this.subclassResponsibility(thisMethod) } text { ^this.subclassResponsibility(thisMethod) } selectedText { ^this.subclassResponsibility(thisMethod) } selectUnderlinedText { | clickPos | ^this.subclassResponsibility(thisMethod) } linkAtClickPos { | clickPos | ^this.subclassResponsibility(thisMethod) } rangeText { | rangestart=0, rangesize=1 | ^this.subclassResponsibility(thisMethod) } prclose { ^this.subclassResponsibility(thisMethod) } closed { onClose.value(this); // call user function this.restoreCurrentEnvironment; allDocuments.remove(this); dataptr = nil; } prinsertText { | dataPtr, txt | ^this.subclassResponsibility(thisMethod) } insertTextRange { | string, rangestart, rangesize | ^this.subclassResponsibility(thisMethod) } prAdd { allDocuments = allDocuments.add(this); this.editable = true; if (autoRun) { if (this.rangeText(0,7) == "/*RUN*/") { this.text.interpret; } }; current = this; initAction.value(this); } //this is called after recompiling the lib *prnumberOfOpen { ^this.subclassResponsibility(thisMethod) } *numberOfOpen { thisProcess.platform.when(\_NumberOfOpenTextWindows) { ^this.prnumberOfOpen } { ^allDocuments.size }; ^0 } *newFromIndex { | idx | ^super.new.initByIndex(idx) } initByIndex { | idx | //allDocuments = allDocuments.add(this); var doc; doc = this.prinitByIndex(idx); if(doc.isNil,{^nil}); this.prAdd; } prinitByIndex { | idx | ^this.subclassResponsibility(thisMethod) } //this is called from the menu: open, new *prGetLast { ^Document.implementationClass.prBasicNew.initLast } initLast { ^this.subclassResponsibility(thisMethod) } prGetLastIndex { ^this.subclassResponsibility(thisMethod) } // private open initFromPath { | path, selectionStart, selectionLength | var stpath; // path = apath; stpath = this.class.standardizePath(path); this.propen(stpath, selectionStart, selectionLength); if(dataptr.isNil,{ this.class.allDocuments.do{ |d| if(d.path == stpath.absolutePath){ ^d } }; ^nil }); this.background_(Color.white); ^this.prAdd; } propen { | path, selectionStart=0, selectionLength=0 | ^this.subclassResponsibility(thisMethod) } // private newTextWindow initByString{ | argTitle, str, makeListener | this.prinitByString(argTitle, str, makeListener); this.background_(Color.white); if(dataptr.isNil,{^nil}); this.prAdd; this.title = argTitle; } prinitByString { | title, str, makeListener | ^this.subclassResponsibility(thisMethod) } // other private // if -1 whole doc prSetBackgroundColor { | color | ^this.subclassResponsibility(thisMethod) } prGetBackgroundColor { | color | ^this.subclassResponsibility(thisMethod) } prSetSelectedBackgroundColor { | color | ^this.subclassResponsibility(thisMethod); } prGetSelectedBackgroundColor { | color | ^this.subclassResponsibility(thisMethod); } selectedRangeLocation { ^this.subclassResponsibility(thisMethod) } selectedRangeSize { ^this.subclassResponsibility(thisMethod) } prSelectLine { | line | ^this.subclassResponsibility(thisMethod) } *prGetIndexOfListener { if (this.implementationClass.isNil) { ^nil }; if (this.implementationClass.respondsTo(\prGetIndexOfListener)) { ^this.implementationClass.prGetIndexOfListener } { ^nil } } //---not yet implemented // ~/Documents // /Volumes // Music/Patches //*reviewUnsavedDocumentsWithAlertTitle //*saveAllDocuments //*recentDocumentPaths //save //saveAs //print // //hasPath was loaded // Environment handling Document with its own envir must set and restore currentEnvironment on entry and exit. // Requires alteration of *open, *new, closed, didBecomeKey, and didResignKey envir_ { | ev | envir = ev; if (this.class.current == this) { if(envir.isNil) { this.restoreCurrentEnvironment } { if (savedEnvir.isNil) { this.saveCurrentEnvironment } } } } restoreCurrentEnvironment { if (savedEnvir.notNil) { currentEnvironment = savedEnvir; savedEnvir = nil; } } saveCurrentEnvironment { if (envir.notNil) { savedEnvir = currentEnvironment; currentEnvironment = envir; } } *prBasicNew { ^super.new } }