// 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
}
}