SystemOrganization addCategory: #'OB-Web-Core'! SystemOrganization addCategory: #'OB-Web-Files'! SystemOrganization addCategory: #'OB-Web-Notifications'! SystemOrganization addCategory: #'OB-Web-Widgets'! Notification subclass: #OBWindowRequest instanceVariableNames: 'model' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Notifications'! OBWindowRequest subclass: #OBCloseWindowRequest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Notifications'! !OBCloseWindowRequest methodsFor: 'as yet unclassified' stamp: 'cwp 5/31/2007 00:27'! handleWith: anObject ^ anObject handleCloseWindow: self! ! OBWindowRequest subclass: #OBOpenWindowRequest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Notifications'! !OBOpenWindowRequest methodsFor: 'as yet unclassified' stamp: 'cwp 5/31/2007 00:27'! handleWith: anObject ^ anObject handleOpenWindow: self! ! !OBWindowRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 5/26/2007 00:14'! for: anObject ^ (self new model: anObject) signal! ! !OBWindowRequest methodsFor: 'as yet unclassified' stamp: 'cwp 5/26/2007 00:15'! model ^ model! ! !OBWindowRequest methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! model: anObject model := anObject! ! OBBuilder subclass: #OBWebBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBWebBuilder class methodsFor: 'as yet unclassified' stamp: 'cwp 10/23/2006 14:55'! new ^ self basicNew initialize! ! !OBWebBuilder methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! addChild: anObject current := anObject! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:55'! button: aModel with: aBlock self shouldNotImplement! ! !OBWebBuilder methodsFor: 'accessing' stamp: 'cwp 10/31/2007 01:42'! current: aWidget do: aBlock super current: aWidget do: aBlock. current addChild: aWidget. ^ aWidget! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:52'! fixedButtonBar: aPanel with: aBlock ! ! !OBWebBuilder methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initialize current := self! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:47'! pane: aColumn with: aBlock ^self current: (OBWebPane model: aColumn) do: [self current: (OBWebList model: aColumn) do: []. aBlock value]! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:53'! radioButtonBar: aSwitch with: aBlock ^self current: (OBWebButtonBar model: aSwitch) do: aBlock! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:46'! scroller: aColumnPanel with: aBlock ^self current: (OBWebScroller model: aColumnPanel) do: aBlock! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 8/11/2007 23:30'! setBalloonText: aString maxLineLength: aSmallInteger ! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:48'! textarea: aPanel with: aBlock ^self current: (OBWebText model: aPanel) do: aBlock! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 23:57'! textfield: aPanel with: aBlock ! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 6/4/2009 02:00'! topNavigationPanel: aPanel with: aBlock ! ! !OBWebBuilder methodsFor: 'building' stamp: 'lr 1/7/2008 11:28'! verticalGroupWith: aBlock aBlock value! ! !OBWebBuilder methodsFor: 'building' stamp: 'cwp 7/25/2007 20:50'! window: aBrowser with: aBlock ^self current: (OBWebWindow model: aBrowser) do: aBlock! ! Object subclass: #OBAjaxMessage instanceVariableNames: 'receiver selector arguments priority' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBAjaxMessage class methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 20:25'! fromJson: aJsonObject ^ self receiver: aJsonObject receiver selector: aJsonObject selector asSymbol arguments: aJsonObject arguments! ! !OBAjaxMessage class methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 21:01'! fromString: aString ^ self fromJson: (Json readFrom: aString readStream)! ! !OBAjaxMessage class methodsFor: 'as yet unclassified' stamp: 'cwp 10/27/2006 00:28'! receiver: aString ^ self basicNew receiver: aString! ! !OBAjaxMessage class methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 20:29'! receiver: receiver selector: selector arguments: arguments ^ self new setReceiver: receiver selector: selector arguments: arguments! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! addArgument: anObject arguments ifNil: [ arguments := #() ]. arguments := arguments copyWith: anObject! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'cwp 5/21/2007 00:08'! arguments ^ arguments value! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! arguments: anArray arguments := anArray! ! !OBAjaxMessage methodsFor: 'receiving' stamp: 'cwp 10/25/2006 20:37'! isAddressedTo: aWidget ^ aWidget identifier = receiver! ! !OBAjaxMessage methodsFor: 'sending' stamp: 'cwp 5/21/2007 00:02'! isDuplicateOf: other ^ self receiver = other receiver and: [self selector = other selector]! ! !OBAjaxMessage methodsFor: 'sending' stamp: 'cwp 5/21/2007 00:08'! jsonWriteOn: aStream aStream nextPut: ${; jsonPrint: 'receiver'; nextPut: $:; jsonPrint: self receiver; nextPutAll: ', '; jsonPrint: 'selector'; nextPut: $:; jsonPrint: self selector; nextPutAll: ', '; jsonPrint: 'arguments'; nextPut: $:; jsonPrint: self arguments; nextPut: $}! ! !OBAjaxMessage methodsFor: 'debugging' stamp: 'cwp 5/27/2007 21:25'! log Transcript cr. self jsonWriteOn: Transcript. Transcript cr. Transcript endEntry.! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'cwp 5/27/2007 22:41'! priority ^ priority ifNil: [0]! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! priority: anInteger priority := anInteger! ! !OBAjaxMessage methodsFor: 'sending' stamp: 'cwp 10/26/2006 19:25'! queue (OBAjaxResponse message: self) signal! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'cwp 5/21/2007 00:03'! receiver ^ receiver! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! receiver: anObject receiver := anObject! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'cwp 10/25/2006 21:34'! selector ^ selector! ! !OBAjaxMessage methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! selector: aSymbol selector := aSymbol! ! !OBAjaxMessage methodsFor: 'receiving' stamp: 'cwp 10/25/2006 21:11'! sendTo: aWidget ^ aWidget perform: selector withArguments: arguments! ! !OBAjaxMessage methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! setReceiver: aString selector: aSymbol arguments: anArray receiver := aString. selector := aSymbol. arguments := anArray! ! Object subclass: #OBHttpService instanceVariableNames: 'dispatcher' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBHttpService methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 01:23'! createLauncher | launcher | launcher := OBWebLauncher new. (dispatcher at: 'windows') at: launcher identifier put: launcher. ^ HttpResponse fromUrl: launcher path! ! !OBHttpService methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! createWindowFor: aBrowser | window | window := OBWebBuilder build: aBrowser. (dispatcher at: 'windows') at: window identifier put: window. ^ window! ! !OBHttpService methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 00:59'! destroyWindowFor: aWebWindow (dispatcher at: 'windows') removeKey: aWebWindow identifier! ! !OBHttpService methodsFor: 'notifications' stamp: 'cwp 5/31/2007 00:27'! handleCloseWindow: req req resume: (self destroyWindowFor: req model)! ! !OBHttpService methodsFor: 'notifications' stamp: 'cwp 5/31/2007 00:28'! handleOpenWindow: req req resume: (self createWindowFor: req model)! ! !OBHttpService methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! initialize dispatcher := Dictionary new. dispatcher at: 'library' put: OBInternalFile dispatcher; at: 'icons' put: OBWebIcons dispatcher; at: 'windows' put: Dictionary new! ! !OBHttpService methodsFor: 'request processing' stamp: 'lr 11/7/2009 18:32'! notFound: aCollection | path | path := String streamContents: [ :stream | aCollection do: [ :ea | stream nextPut: $/. stream nextPutAll: ea ] ]. ^ HttpResponse status: #notFound contents: path , ' was not found on this server'! ! !OBHttpService methodsFor: 'request processing' stamp: 'lr 11/7/2009 18:32'! processAjax: aString for: target | message content | message := OBAjaxMessage fromString: aString. content := Json render: (target processMessage: message). ^ self responseWithContent: content type: 'application/json; charset=utf-8'! ! !OBHttpService methodsFor: 'request processing' stamp: 'cwp 10/10/2007 01:19'! processGetFor: target ^self responseWithContent: target contents type: target contentType! ! !OBHttpService methodsFor: 'request processing' stamp: 'cwp 11/1/2007 22:43'! processPath: path content: content type: type | target | path ifEmpty: [^self createLauncher]. target := dispatcher resolvePath: path ifAbsent: [^self notFound: path]. ^ [type = 'application/json' ifTrue: [self processAjax: content for: target] ifFalse: [self processGetFor: target]] on: OBWindowRequest do: [:req | req handleWith: self]! ! OBHttpService subclass: #OBKomHttpService instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! OBKomHttpService class instanceVariableNames: 'port service'! OBKomHttpService class instanceVariableNames: 'port service'! !OBKomHttpService class methodsFor: 'as yet unclassified' stamp: 'cwp 7/10/2007 01:44'! createService "Cribbed from Seaside" Smalltalk at: #HttpService ifPresent: [:hs | ^ (hs on: port named: 'OmniBrowser') plug: self new]. Smalltalk at: #ComancheNetService ifPresent: [:cns | ^ (cns named: 'OmniBrowser' onPort: port) module: self new]. self error: 'Comanche is not installed.'! ! !OBKomHttpService class methodsFor: 'as yet unclassified' stamp: 'cwp 7/10/2007 01:26'! initialize Smalltalk addToStartUpList: self after: AutoStart. Smalltalk addToShutDownList: self! ! !OBKomHttpService class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! startOn: aPort self stop. port := aPort. service := self createService. service start. ^ service! ! !OBKomHttpService class methodsFor: 'as yet unclassified' stamp: 'cwp 7/10/2007 01:25'! startUp port ifNotNil: [self startOn: port]! ! !OBKomHttpService class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! stop service ifNotNil: [ service unregister. service := nil ]. port := nil! ! !OBKomHttpService methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 00:41'! processError: anError self halt. ^ HttpResponse basicNew status: #serverError; contentType: MIMEDocument contentTypePlainText; contents: (anError class name, ': ', anError messageText) readStream; yourself! ! !OBKomHttpService methodsFor: 'as yet unclassified' stamp: 'cwp 10/28/2007 19:47'! processHttpRequest: aRequest ^ [self processPath: aRequest pathParts content: (aRequest stream next: aRequest contentLength) type: aRequest contentType] on: Error do: [:error | self processError: error]! ! !OBKomHttpService methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 01:14'! responseWithContent: content type: type ^ HttpResponse fromString: content contentType: type! ! Object subclass: #OBInternalFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBInternalFile commentStamp: 'cwp 8/11/2007 23:10' prior: 0! My subclasses represent css and javascript files that implement the OB web client.! OBInternalFile subclass: #OBBrowserFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBBrowserFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:36'! contentType ^ 'text/css'! ! !OBBrowserFile methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2009 04:51'! contents ^ ' body { font-family: Palatino, Georgia, serif; /* font-family: Bitstream Vera Serif, serif;*/ font-size: 10pt; } div { position: absolute; overflow: auto; } .root { position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; } .vertical { left: 0px; right: 0px; } .horizontal { top: 0px; bottom: 0px; } div.list { border: 1px #CCE3C8 solid; cursor: default; } .list { padding: 3px; margin: 1px; } .list img { margin-right: 2px; vertical-align: text-top; } .list li { list-style-type: none; white-space: nowrap; right: 2px; overflow: hidden; } li.blank { padding-left: 15px; } div.menu { background-color: #CCE3C8; position: absolute; } div.prompt { display: inline-block; position: relative; left: 4px; right: 4px; padding: 4px; margin-bottom: 4px; text-align: center; background-color: #B5DEAD; white-space: pre; /* CSS2 */ white-space: -moz-pre-wrap; /* Mozilla */ white-space: pre-wrap; /* CSS 2.1 */ word-wrap: break-word; /* IE */ } ul.menu { padding: 8px; margin: 0px; cursor: default; } .menu li { list-style-type: none; white-space: nowrap; margin: 0; } .menu li:hover, .button-bar .selection { background-color: #B5DEAD; } .button-bar, .list .selection { background-color: #CDE9C1; } .button-bar { text-align: center; line-height: 100%; overflow: hidden; margin: 1px; } .button { position: relative; top: 2px; padding-top: 3px; padding-bottom: 3px; padding-left: 6px; padding-right: 6px; cursor: default; } div.Text { border: 1px #CCE3C8 solid; margin: 1px; } div.Text.dirty { border: 1px red solid; } div.Content { font-family: Georgia, serif; font-size: 10pt; white-space: pre; /* CSS2 */ white-space: -moz-pre-wrap; /* Mozilla */ white-space: pre-wrap; /* CSS 2.1 */ word-wrap: break-word; /* IE */ outline: none; top: 5px; bottom: 5px; left: 5px; right: 5px; } '! ! !OBBrowserFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:27'! name ^ 'browser.css'! ! OBInternalFile subclass: #OBEditorFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBEditorFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:37'! contentType ^ 'text/css'! ! !OBEditorFile methodsFor: 'as yet unclassified' stamp: 'cwp 10/18/2007 23:19'! contents ^ 'body { font-family: Georgia, serif; font-size: 10pt; white-space: pre; /* CSS2 */ white-space: -moz-pre-wrap; /* Mozilla */ white-space: pre-wrap; /* CSS 2.1 */ word-wrap: break-word; /* IE */ } .editor { top: 5px; bottom: 5px; left: 5px; right: 5px; } '! ! !OBEditorFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:27'! name ^ 'editor.css'! ! !OBInternalFile class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! allFiles | files | files := SortedCollection sortBlock: [ :a :b | a name <= b name ]. self allSubclassesDo: [ :ea | files add: ea new ]. ^ files asArray! ! !OBInternalFile class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! dispatcher | dispatcher file | dispatcher := Dictionary new. self allSubclassesDo: [ :ea | file := ea new. dispatcher at: file name put: file ]. ^ dispatcher! ! !OBInternalFile methodsFor: 'accessing' stamp: 'cwp 8/2/2007 22:37'! contentType ^ 'text/javascript'! ! !OBInternalFile methodsFor: 'printing' stamp: 'cwp 8/3/2007 00:06'! printOn: aStream aStream nextPutAll: self name! ! OBInternalFile subclass: #OBLauncherFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBLauncherFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:21'! contents ^ 'function Widget() {}; Widget.widgets = new Object; Widget.get = function(id) { return this.widgets[id]; } function Launcher(id) { this.id = id; this.windows = new Array; Widget.widgets[id] = this; } Launcher.prototype = new Widget(); Launcher.prototype.openBrowser = function() { link.send(this.id, ''openBrowser''); }; Launcher.prototype.openWindow = function(url) { var child = window.open(url,'''',''scrollbars=no,menubar=no,height=400,width=600,resizable=yes,toolbar=no,location=no,status=no''); this.windows.push(child); }; '! ! !OBLauncherFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:28'! name ^ 'launcher.js'! ! OBInternalFile subclass: #OBLinkFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBLinkFile methodsFor: 'as yet unclassified' stamp: 'cwp 10/29/2007 00:52'! contents ^ 'function Link(url) { this.url = url; this.objects = new Object; this.beats = []; } Link.log = function(val) { if (window.console) { window.console.log(val); } else if (document.createEvent) { printfire=function(){} printfire.args = arguments; var ev = document.createEvent("Events"); ev.initEvent("printfire", false, true); dispatchEvent(ev); } else { window.alert(val + "\n"); } } Link.prototype.register = function(object) { this.objects[object.id] = object; }; Link.prototype.printValue = function(val) { var str; switch(val) { case undefined: str = ''null''; break; case null: str = ''null''; break; case true: str = ''true''; break; case false: str = ''false''; break; default: str = this.printObject(val); } return str; }; Link.prototype.printObject = function(obj) { var str=[]; switch(obj.constructor) { case Boolean: case Number: str.push(obj); break; case String: str.push("\"", obj, "\""); break; case Array: for (var i=0; i < obj.length; i++) { str.push(this.printValue(obj[i])); }; str=["[", str.join(", "), "]"]; break; default: for (var p in obj) { str.push("\"" + p + "\": " + this.printValue(obj[p])); }; str = ["{", str.join(", "), "}"]; break; }; return str.join(""); } Link.prototype.message = function(receiver, selector) { var msg = {receiver: receiver, selector: selector}; msg.arguments = new Array(); for (var i=2; i= 0; i--){ this.beats[i].reset }; } Link.prototype.post = function(msg) { var self = this; var req = new XMLHttpRequest(); req.open(''POST'', this.url, true); req.onreadystatechange = function() { self.handleStateChange(req); } req.setRequestHeader(''Content-Type'', ''application/json''); req.send(this.printValue(msg)); } Link.prototype.dispatch = function(messages) { var msg, receiver; for (var i=0; i < messages.length; i++) { msg = messages[i]; receiver = Widget.get(msg.receiver); receiver[msg.selector].apply(receiver, msg.arguments) }; }; function Heartbeat (seconds, message) { this.seconds = seconds; this.message = message; this.reset(); } Heartbeat.prototype.reset = function() { var self = this; var func = function() {link.post(self.message)}; if (this.id) window.clearInterval(this.id); this.id = window.setInterval(func, this.seconds * 1000); }; link = new Link(window.location); '! ! !OBLinkFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:28'! name ^ 'link.js'! ! OBInternalFile subclass: #OBTextFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBTextFile methodsFor: 'as yet unclassified' stamp: 'cwp 6/7/2009 01:29'! contents ^ 'Text = function(id) { this.id = id; this.border = document.getElementById(id); this.node = document.createElement(''div''); this.node.className = ''Content''; this.node.innerHTML = ''

''; this.node.contentEditable = ''true''; this.border.appendChild(this.node); this.codes = new Object; if (Widget.mozilla) this.configMozilla() else this.configSafari(); } Text.prototype = new Widget(); Text.prototype.configMozilla = function() { document.execCommand(''enableObjectResizing'', false, false); window.addEventListener(''load'', this.thunk(''installHandlers''), false); this.insertCommand = ''inserthtml''; with (this.codes) { circumflex = 94; underscore = 95; tab = 9; save = 115; implementors = 109; senders = 110; references = 78; browse = 98; } this.contents = function() { var result = this.node.innerHTML; result = result.replace(''
'', "\n", ''gm''); return result } }; Text.prototype.configSafari = function() { setTimeout(this.thunk(''installHandlers''), 0); this.insertCommand = ''inserttext''; with (this.codes) { circumflex = 94; underscore = 95; tab = 9; save = 19; senders = 14; implementors = 13; references = 13; browse = 2; } this.contents = function() { return this.encode(this.node.innerText); } }; Text.prototype.installHandlers = function() { this.node.addEventListener(''keypress'', this.thunk(''handleKeystroke''), false); this.node.addEventListener(''contextmenu'', this.thunk(''handleContextMenu''), false); }; Text.prototype.init = function(state) { // if (Widget.mozilla) // document.addEventListener(''load'', this.cont(''update'', state), false); // else setTimeout(this.cont(''update'', state), 0); }; Text.prototype.decode = function(text) { var result = text; result = result.replace("\r", "\n", ''gm''); result = result.replace(''_'', "\u2190", ''gm''); result = result.replace(''^'', "\u2191", ''gm''); return result }; Text.prototype.encode = function(text) { var result = text; result = result.replace("\n", "\r", ''gm''); result = result.replace("\u2190", ''_'', ''gm''); result = result.replace("\u2191", ''^'', ''gm''); return result }; Text.prototype.update = function(state) { this.node.innerHTML = this.decode(state.text); this.markClean(); }; Text.prototype.handleKeystroke = function(evt) { var target, code; if (!!evt) var evt = window.event; if (evt.target) target = evt.target; else if (evt.srcElement) target = evt.srcElement; if (target.nodeType == 3) target = target.parentNode; if (evt.keyCode) code = evt.keyCode; else if (evt.which) code = evt.which; with (this.codes) { if (evt.ctrlKey) { if (evt.shiftKey) { if (references == code) this.sendCommand(''references:'') } else { if (save == code) this.save() else if (implementors == code) this.sendCommand(''implementors:'') else if (senders == code) this.sendCommand(''senders:'') else if (browse == code) this.sendCommand(''browse:'') } } else { if (circumflex == code) this.upArrow(evt) else if (underscore == code) this.leftArrow(evt) } } this.markDirty() } Text.prototype.handleContextMenu = function(evt) { evt.preventDefault(); if (Widget.processEvents) this.requestMenu(evt); }; Text.prototype.markDirty = function() { if (-1 == this.border.className.indexOf(''dirty'')) this.border.className += '' dirty'' }; Text.prototype.markClean = function() { this.border.className = this.border.className.replace('' dirty'', '''') }; Text.prototype.requestMenu = function(evt) { if (!!evt) var evt = window.event; Menu.x = evt.pageX + this.iframe.parentNode.offsetLeft; Menu.y = evt.pageY + this.iframe.parentNode.offsetTop; link.send(this.id, ''menuShifted:selection:'', evt.shiftKey, this.getSelection()) }; Text.prototype.getSelection = function() { return this.win.getSelection().toString() }; Text.prototype.sendCommand = function(command) { link.send(this.id, command, this.getSelection()); }; Text.prototype.upArrow = function(evt) { evt.preventDefault(); document.execCommand(this.insertCommand, false, "\u2191"); }; Text.prototype.leftArrow = function(evt) { evt.preventDefault(); document.execCommand(this.insertCommand, false, "\u2190"); }; Text.prototype.save = function() { var contents = this.encode(this.contents()); link.send(this.id, ''accept:'', contents); }; Text.prototype.tab = function() {}; '! ! !OBTextFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:29'! name ^ 'text.js'! ! OBInternalFile subclass: #OBWidgetsFile instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! !OBWidgetsFile methodsFor: 'as yet unclassified' stamp: 'cwp 6/7/2009 01:41'! contents ^ ' Widget = function() {}; Widget.processEvents = true; Widget.safari = (-1 < navigator.userAgent.toLowerCase().indexOf(''safari'')); Widget.mozilla = (-1 < navigator.userAgent.toLowerCase().indexOf(''firefox'')); Widget.init = function(id) { this.widgets = new Object; var root = document.getElementById(id); this.bind(root); var children = root.getElementsByTagName(''DIV''); for (var i=0; i < children.length; i++) { this.bind(children.item(i)); }; } Widget.bind = function(node) { var klass = node.className.split('' '')[0]; if (window[klass]) this.widgets[node.id] = new window[klass](node.id); } Widget.unbind = function(node) { delete this.widgets[node.id]; }; Widget.get = function(id) { return this.widgets[id]; } Widget.prototype.thunk = function(method) { var self = this; return function() {return self[method].apply(self, arguments)}; }; Widget.prototype.cont = function(method) { var self = this; var len = arguments.length; var args = new Array(len - 1); for (var i=1; i < len; i++) { args[i-1] = arguments[i]; }; return function() {return self[method].apply(self, args)}; }; Widget.prototype.children = function() { var nodes = this.div.childNodes; var length = nodes.length; var result = new Array; for (var i=0; i < length; i++) { if (nodes[i].nodeType == Node.ELEMENT_NODE) result.push(nodes[i]); }; return result; }; Widget.prototype.requestText = function(prompt, template) { var text = window.prompt(prompt, template); link.send(this.id, ''continue:'', text); }; Widget.prototype.requestChoice = function(prompt, labels) { var items = new Array(labels.length); for (var i = labels.length - 1; i >= 0; i--){ items[i] = {label: labels[i], isEnabled: true}; }; if (prompt) prompt = prompt.replace("\r", "\n", ''gm''); menu = new Menu(this.id, prompt, items); menu.show(Menu.x, Menu.y); }; Widget.prototype.openMenu = function(spec) { menu = new Menu(this.id, '''', spec.items); menu.show(Menu.x, Menu.y); }; Widget.prototype.openWindow = function(url) { window.opener.launcher.openWindow(url); } Root = function(id) { this.id = id; this.div = document.getElementById(id); link.heartbeat(5, this.id, ''ping'') } Root.prototype = new Widget; Root.prototype.title = function(title) { document.title = title; }; SelectingWidget = function() {} SelectingWidget.prototype = new Widget(); SelectingWidget.prototype.installHandler = function(id) { var self = this; this.node.onclick = function(evt) { if (Widget.processEvents) self.select(evt.target) }; }; SelectingWidget.prototype.update = function(state) { this.node.innerHTML = ''''; var length = state.items.length; for (var i=0; i < length; i++) { this.node.appendChild(this.createItemNode(state, i)); }; if (state.selection !!= undefined) this.node.childNodes[state.selection].className += '' '' + this.selectedClass; this.noteSelection(this.node.childNodes[state.selection]); }; SelectingWidget.prototype.select = function(node) { if (node.nodeName == this.element) { var label = this.decode(node); link.send(this.id, ''select:'', label); } }; SelectingWidget.prototype.selectedNode = function() { var nodes = this.node.childNodes; var length = nodes.length; for (var i=0; i < length; i++) if (nodes[i].className == this.selectedClass) return nodes[i] return null; }; SelectingWidget.prototype.isEmpty = function() { return this.node.childNodes.length == 0; }; SelectingWidget.prototype.noteSelection = function(node) { // do nothing be default }; function ButtonBar (id) { this.id = id; this.node = document.getElementById(id); this.node.innerHTML = ''''; this.node.className += '' button-bar''; this.installHandler(); } ButtonBar.prototype = new SelectingWidget; ButtonBar.prototype.element = ''SPAN''; ButtonBar.prototype.unselectedClass = ''button''; ButtonBar.prototype.selectedClass = ''button selection''; ButtonBar.prototype.createItemNode = function(state, index) { var element = document.createElement(this.element); element.className = this.unselectedClass; element.innerHTML = state.items[index]; return element; }; ButtonBar.prototype.decode = function(node) { return node.firstChild.data }; function List(id) { this.id = id; var div = document.getElementById(id); div.innerHTML = ''''; this.node = document.createElement(''ul''); this.node.className = ''list''; div.appendChild(this.node); this.node.onclick = this.thunk(''handleClick''); this.node.oncontextmenu = this.thunk(''handleContextMenu''); } List.prototype = new SelectingWidget; List.prototype.element = ''LI''; List.prototype.selectedClass = ''selection''; SelectingWidget.prototype.createItemNode = function(state, index) { var element = document.createElement(this.element); if (state.icons.length > 0) { if (state.icons[index] == ''blank'') { element.className = ''blank''; } else { var image = new Image(); image.src = ''/icons/'' + state.icons[index]; image.width = 12; image.height = 12; element.appendChild(image); }; } var label = document.createTextNode(this.encode(state.items[index])); element.appendChild(label); return element; }; List.prototype.noteSelection = function(node) { if (undefined == node) return; var div = this.node.parentNode; var nodeBottom = node.offsetTop + node.offsetHeight; var divBottom = div.scrollTop + div.offsetHeight; if ((node.offsetTop < div.scrollTop) || (nodeBottom > divBottom)) { var middle = node.offsetTop + Math.floor((node.offsetHeight / 2)); div.scrollTop = middle - Math.floor((div.offsetHeight / 2)); }; }; List.prototype.handleClick = function(evt) { evt.preventDefault(); if (Widget.processEvents) this.select(evt.target); }; List.prototype.handleContextMenu = function(evt) { evt.preventDefault(); if (Widget.processEvents) this.requestMenu(evt); }; List.prototype.encode = function(label) { label = label.replace('' '', "\u00A0", ''g''); label = label.replace(''>>'', "\u00BB", ''g''); return label; }; List.prototype.decode = function(node) { var label = node.lastChild.data; label = label.replace("\u00A0", '' '', ''g'') label = label.replace('' '', '' '', ''g''); label = label.replace(''>'', ''>'', ''g''); label = label.replace("\u00BB", ''>>'', ''g''); return label; }; List.prototype.requestMenu = function(evt) { if (!!evt) var evt = window.event; Menu.noteLocation(evt); link.send(this.id, ''openMenu'') }; Menu = function(id, prompt, items) { this.id = id; this.prompt = prompt; this.items = items; this.saved = new Object; } Menu.noteLocation = function(evt) { Menu.x = evt.pageX; Menu.y = evt.pageY; } Menu.clearLocation = function() { Menu.x = Math.floor(window.innerWidth / 2); Menu.y = Math.floor(window.innerHeight / 2); } Menu.clearLocation(); Menu.prototype = new Widget; Menu.prototype.installHandlers = function() { this.saved.onmousedown = document.body.onmousedown; this.saved.onmouseup = document.body.onmouseup; document.body.onmousedown = this.thunk(''handleMouseDown''); document.body.onmouseup = this.thunk(''handleMouseUp''); }; Menu.prototype.removeHandlers = function() { document.body.onmousedown = this.saved.onmousedown; document.body.onmouseup = this.saved.onmouseup; }; Menu.prototype.handleMouseUp = function(evt) { if (!!evt) var evt = window.event; var target = (window.event) ? evt.srcElement : evt.target; var node = target; while (node !!= this.node && node.nodeName !!= ''BODY'') node = node.parentNode; if (node == this.node) { Menu.noteLocation(evt); this.select(target); } else this.hide(); }; Menu.prototype.handleMouseDown = function(evt) { evt.preventDefault() }; Menu.prototype.show = function(x, y) { var ul = document.createElement(''ul''); var item; this.node = document.createElement(''div''); this.node.className = ''menu''; if (this.prompt) { var prompt = document.createElement(''div''); prompt.className = ''prompt''; prompt.appendChild(document.createTextNode(this.prompt)); this.node.appendChild(prompt); } ul.className = ''menu''; this.node.appendChild(ul); var len = this.items.length; for (var i=0; i < len; i++) { if (null == this.items[i]) { item = document.createElement(''hr''); } else { item = document.createElement(''li''); item.appendChild(document.createTextNode(this.items[i].label)); } ul.appendChild(item); }; Widget.processEvents = false; setTimeout(this.thunk(''installHandlers''), 10); document.body.appendChild(this.node); this.position(x, y); }; Menu.prototype.position = function(x, y) { // measure the node and the window var mw = this.node.offsetWidth; var mh = this.node.offsetHeight; var ww = document.body.clientWidth; var wh = document.body.clientHeight; // offset from the mouse a bit x += 5; y -= 12; // move so that it''s entirely inside the window x = x + mw < ww ? x : ww - mw; y = y + mh < wh ? y : wh - mh; this.node.style.left = x; this.node.style.top = y; }; Menu.prototype.hide = function() { this.node.parentNode.removeChild(this.node); this.removeHandlers(); window.setTimeout(function() {Widget.processEvents = true}, 100); Menu.clearLocation(); }; Menu.prototype.select = function(node) { if (node.nodeName == ''LI'') link.send(this.id, ''continue:'', node.innerHTML); this.hide() }; Scroller = function(id) { this.id = this.id; this.div = document.getElementById(id); } Scroller.prototype = new Widget(); Scroller.prototype.adjustPanes = function() { var panes = this.children(); var sizing = this.sizing ? this.sizing : panes.length; var width = 100 / sizing; for (var i=0; i < panes.length; i++) { var p = panes[i]; p.style.left = width*i + ''%''; p.style.right = (100 - width - width * i) + ''%''; }; this.div.scrollLeft = this.div.scrollWidth - this.div.style.width; }; Scroller.prototype.push = function(spec) { var pane = document.createElement(''div''); pane.id = spec.id; pane.className = ''Pane horizontal''; var list = document.createElement(''div''); list.id = spec.list; list.className = ''List vertical''; pane.appendChild(list); var buttons = document.createElement(''div''); buttons.id = spec.buttons; buttons.className = ''ButtonBar vertical'' pane.appendChild(buttons); this.div.appendChild(pane); Widget.bind(pane); Widget.bind(list); Widget.bind(buttons); if (spec.show) { Widget.get(spec.id).showSwitch(); } else { Widget.get(spec.id).hideSwitch(); } this.adjustPanes(); }; Scroller.prototype.pop = function(count) { for (var i=0; i < count; i++) { pane = this.div.lastChild; Widget.unbind(pane); this.div.removeChild(this.div.lastChild); }; this.adjustPanes(); }; Scroller.prototype.setSizing = function(sizing) { this.sizing = sizing; this.adjustPanes(); }; Pane = function (id) { this.id = id; this.div = document.getElementById(id); } Pane.prototype = new Widget(); Pane.prototype.isShowing = function() { return Widget.get(this.children()[1].id).isEmpty(); }; Pane.prototype.update = function(shouldShow) { var isShowing = this.isShowing(); if (shouldShow && !!isShowing) { this.showSwitch(); } else if (!!shouldShow && isShowing) { this.hideSwitch(); } }; Pane.prototype.showSwitch = function() { var children = this.children(); children[0].style.top = ''0px''; children[0].style.bottom = ''18px''; children[1].style.display = ''block''; children[1].style.bottom = ''0px''; children[1].style.height = ''18px''; }; Pane.prototype.hideSwitch = function() { var children = this.children(); children[0].style.top = ''0px''; children[0].style.bottom = ''0px''; children[1].style.display = ''none''; children[1].style.bottom = ''0px''; children[1].style.height = ''18px''; };'! ! !OBWidgetsFile methodsFor: 'as yet unclassified' stamp: 'cwp 8/2/2007 22:29'! name ^ 'widgets.js'! ! Object subclass: #OBSubcomputation instanceVariableNames: 'context' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBSubcomputation class methodsFor: 'as yet unclassified' stamp: 'cwp 8/14/2007 23:37'! do: aBlock ^ aBlock value: (self withContext: thisContext)! ! !OBSubcomputation class methodsFor: 'as yet unclassified' stamp: 'cwp 8/14/2007 23:45'! resume: aSubcontinuation self do: [:subcomp | aSubcontinuation value: subcomp]! ! !OBSubcomputation class methodsFor: 'as yet unclassified' stamp: 'cwp 2/11/2007 11:17'! withContext: anActivationContext ^ self new initializeWithContext: anActivationContext! ! !OBSubcomputation methodsFor: 'as yet unclassified' stamp: 'cwp 6/18/2007 23:39'! callWithCurrentSubcontinuation: aBlock ^ aBlock value: (OBSubcontinuation from: thisContext sender to: context)! ! !OBSubcomputation methodsFor: 'as yet unclassified' stamp: 'cwp 6/18/2007 23:39'! callcs: aBlock ^ aBlock value: (OBSubcontinuation from: thisContext sender to: context)! ! !OBSubcomputation methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! escape: aBlock | continuation | continuation := OBSubcontinuation from: thisContext sender to: context. thisContext swapSender: context. ^ aBlock value: continuation! ! !OBSubcomputation methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! initializeWithContext: anActivationContext context := anActivationContext! ! !OBSubcomputation methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! terminate: v | frame | frame := thisContext sender. [ frame == context ] whileFalse: [ frame := frame swapSender: nil ]. thisContext swapSender: context. ^ v! ! Object subclass: #OBSubcontinuation instanceVariableNames: 'joinPoint values' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBSubcontinuation class methodsFor: 'as yet unclassified' stamp: 'cwp 2/11/2007 11:21'! from: start to: end ^ self basicNew initializeFrom: start to: end! ! !OBSubcontinuation methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! initializeFrom: start to: end | valueStream context | valueStream := WriteStream on: (Array new: 20). context := start. [ context ~~ end and: [ context notNil ] ] whileTrue: [ valueStream nextPut: context. 1 to: context class instSize do: [ :i | valueStream nextPut: (context instVarAt: i) ]. 1 to: context size do: [ :i | valueStream nextPut: (context at: i) ]. joinPoint := context. context := context sender ]. values := valueStream contents! ! !OBSubcontinuation methodsFor: 'as yet unclassified' stamp: 'cwp 2/11/2007 11:45'! joinPoint ^ joinPoint! ! !OBSubcontinuation methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! restoreValues | valueStream context | valueStream := values readStream. [ valueStream atEnd ] whileFalse: [ context := valueStream next. 1 to: context class instSize do: [ :i | context instVarAt: i put: valueStream next ]. 1 to: context size do: [ :i | context at: i put: valueStream next ] ]! ! !OBSubcontinuation methodsFor: 'as yet unclassified' stamp: 'cwp 2/11/2007 13:13'! value: v self restoreValues. joinPoint swapSender: thisContext sender. thisContext swapSender: values first. ^ v! ! Object subclass: #OBWebIcons instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Files'! OBWebIcons class instanceVariableNames: 'icons'! OBWebIcons class instanceVariableNames: 'icons'! !OBWebIcons class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! compileIcon: aSelector form: aForm | bytes source | bytes := ByteArray streamContents: [ :s | PNGReadWriter putForm: aForm onStream: s ]. source := String streamContents: [ :stream | stream nextPutAll: aSelector; cr; tab; nextPutAll: '^ MIMEDocument'; cr; tab; tab; nextPutAll: 'contentType: ''image/png'''; cr; tab; tab; nextPutAll: 'content: '; cr; cr; print: bytes asString ]. self compile: source classified: 'icons'! ! !OBWebIcons class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! copyFromMorphic | class form | class := Smalltalk at: #OBMorphicIcons ifAbsent: [ ^ self ]. class selectors do: [ :sel | form := class iconNamed: sel. (form isKindOf: Form) ifTrue: [ self compileIcon: sel form: form ] ]! ! !OBWebIcons class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! dispatcher | dispatcher inst | dispatcher := Dictionary new. inst := self new. self selectors do: [ :selector | dispatcher at: selector asString put: (inst perform: selector) ]. ^ dispatcher! ! !OBWebIcons class methodsFor: 'as yet unclassified' stamp: 'cwp 8/12/2007 13:27'! iconNamed: aSymbol ^ icons at: aSymbol ifAbsentPut: [[self new perform: aSymbol] on: MessageNotUnderstood do: [:exc | self iconNamed: #blank]]! ! !OBWebIcons class methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! initialize icons := IdentityDictionary new! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! arrowDown ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE]h^RWYSX{YbDfEtRNSd2s@IDATx^]I  $S =dy$X]@DTP -NP|V4IENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! arrowUp ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE]h^RWYSX{YbDfEtRNSd2sBIDATx^eQ0n:^R`ցm"Uw9M ,62^q3JIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! arrowUpAndDown ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEbD{YhX]^RSWYY"tRNSd2sCIDATx^UQ0C:V_2}ISGm ڑDy_ADqIA_JAG;/U^6n+IENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! blank ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE???___''''''///777GGGOOOWWWgggooowww2e222e2222e2eeeeee2e˘2e2e2222e222222222e22222222e22e2ee2e2e2e2222e22˘22222e2222222e222ee2eeeeee2e22ee2e2e2e2eee2eeeeeeeeeeee2eeee˘eee2eeeeeee2eeeee2e222e2222e2eeeeee2e˘˘2˘e˘˘˘˘2e2e˘222e2˘222e2eee˘eee2e˘˘2e˘2e˘2e222e2222e2eeeeee2e˘2e2eD !! IDATx^cfjIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! breakpoint ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEX5S2_:uDD3.QJ ""44KKPPUUXX\\bbllzz3CtRNS[oZIDATx^] @Q?;( HGމhPG4jEc炆a*VAV>3-Qu36 m 4PUAAaddbffƭh qe20a?q$IENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! exception ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEcݙNppbI_MeIk\ai~exoݦsڊ߃VxxCm7p8nFϑUIdd]aՆNUZhu;ܨgxl<߯7rI~digߚf٢?YMGp{WRZ;tRNSBIDATx^5EWR۶m۽MVٓC<>Aq''{3wUaRL[Lr͞6t+QŤb~<]p:#pfCIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! flag ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE7d9~w?CEHLRYdj<=;98a9X5S2uD tRNS[oZIDATx^]K EQ+>D㝝IYoKG, \I>UW50Z3aGXcR*e~p PIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! magnitude ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE^^^iiijjjaaaqqqnnnlll‡...444sssgggVVVUUUdddߊ<<<}}}󺺺LLLrrroooxxxFtRNSOjIDATx^EG@DAPAQ9#?̔_t4>d @{/pgU3i#һLIth3oVLkR&ۿŽIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! morph ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE䅮፳}}ɔ哪xثsƀ僠ً̉޸сۢ焧ծ܉iʫ܃ڔŃꇪس٣tf⁠˒؀ŏɊeYҎݧն۬ڈx͓\쵗O=~Ëɒz~ɰkk些ӟ͊ڮ߭ߊbVˎ{ʼnᄬNtRNS`IDATx^c`̕UPwb(d`dc 2 bᷕ.筮eba0w͔e+Rd/6HsbKINasaȲqPu6c/U p+efHH7v wWW.a)2UJb47M gɋdGQV%IENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! string ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEoqrnoppl}mn~ymqnmsjqspnnporpopnntRNS<aIDATx^5Y AcE''Ԣ>1Xyo)PUUn߂Xt*8&pib}l< rYAXry 6B2GIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! testGray ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEºݵ횚ٰԶ򌌌ܯ tRNSaAIDATx^cA|QFIf(Eab`rxٸXqv&V~([P=p? gOIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! testGreen ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEܜ^Y˒ӡˈTLUN֗^X߹ܳɃῐŒ]W^YUOҙWPѕϙ֚Ϛ͘ʑӢˊʗX:tRNSAIDATx^cPVFe|1ai(IaPreqyV)A9(EI=p27BrIENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! testOrange ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTEǍ˓޵~~tثz~˔…}mŇ7>Ō})nĈ)~<:ʆ)v) tRNSAIDATx^cPVFe|Y>f(ATʑacUr8$yNFA 6(GLZJ=p/#IENDB`'! ! !OBWebIcons methodsFor: 'icons' stamp: 'cwp 6/20/2009 00:55'! testRed ^ MIMEDocument contentType: 'image/png' content: 'PNG  IHDR aPLTE~-)-)~~)/,)~)/~)-wxvosm).kf~}||~-){{tRNSAIDATx^cPVFe|196A(QDFaVr8$.EQ~V(GG]R=p0IENDB`'! ! Object subclass: #OBWebIdentifier instanceVariableNames: 'id' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:07'! basicNew: aNumber ^ self basicNew initializeWithSize: aNumber! ! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'cwp 10/24/2006 11:23'! defaultSize ^ 16! ! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'cwp 10/24/2006 11:22'! new ^ self new: self defaultSize! ! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:07'! new: aNumber ^ (self basicNew: aNumber) randomizeWith: Random new! ! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:07'! random: aRandom ^ (self basicNew: self defaultSize) randomizeWith: aRandom! ! !OBWebIdentifier class methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 13:51'! seed: anInteger ^ self random: (Random seed: anInteger)! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:09'! = other ^ other species = self species and: [other printString = self printString]! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'cwp 1/27/2008 01:37'! asNumber ^ id! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:09'! hash ^ self printString hash! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! initializeWithSize: aNumber id := LargePositiveInteger new: aNumber! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! printOn: aStream | base digits current i letters quo | base := 36. digits := '0123456789abcdefghijklmnopqrstuvwxyz'. current := id. i := id digitLength * 8. letters := String new: i. [ current < base ] whileFalse: [ quo := current quo: base. letters at: i put: (digits at: current - (quo * base) + 1). i := i - 1. current := quo ]. letters at: i put: (digits at: current + 1). aStream nextPut: $w. aStream nextPutAll: (letters copyFrom: i to: letters size)! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:08'! printString ^ String streamContents: [:stream | self printOn: stream]! ! !OBWebIdentifier methodsFor: 'as yet unclassified' stamp: 'avi 12/5/2007 12:05'! randomizeWith: aRandom 1 to: id size do: [:i | id at: i put: (aRandom nextInt: 255)]! ! Object subclass: #OBWebLauncher instanceVariableNames: 'id queue' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 5/31/2007 01:12'! allowedSelectors ^ #(openBrowser close)! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 5/31/2007 01:12'! close OBCloseWindowRequest for: self! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 00:25'! contentType ^ 'text/html'! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 00:25'! contents ^ ' launcher '! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! flushQueue | tmp | tmp := queue asArray. queue := OrderedCollection new. ^ tmp! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/18/2006 18:19'! id ^ id! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/18/2006 18:19'! identifier ^ id asString! ! !OBWebLauncher methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initialize id := UUID new. queue := OrderedCollection new! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! openBrowser | window | window := OBOpenWindowRequest for: OBSystemBrowser new. self queueMessage: ((JsonObject new) receiver: 'id1'; selector: 'openWindow'; arguments: {window path}; yourself)! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/10/2007 00:18'! path ^ '/windows/', id asString! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/20/2006 23:29'! processMessage: aMessage (self allowedSelectors includes: aMessage selector) ifTrue: [aMessage sendTo: self] ifFalse: [self webDoesNotUnderstand: aMessage]. ^ self flushQueue! ! !OBWebLauncher methodsFor: 'as yet unclassified' stamp: 'cwp 10/20/2006 22:17'! queueMessage: aMessageSend queue add: aMessageSend! ! Object subclass: #OBWebLink instanceVariableNames: 'root objects queue mutex computation continuation' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBWebLink methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! at: identifier put: anObject objects ifNil: [ objects := Dictionary new. root := anObject ]. objects at: identifier put: anObject! ! !OBWebLink methodsFor: 'messaging' stamp: 'cwp 10/31/2007 00:01'! createMessage ^ OBAjaxMessage receiver: root identifier! ! !OBWebLink methodsFor: 'messaging' stamp: 'lr 11/7/2009 18:32'! deliverMessage: aMessage | receiver | aMessage selector = #continue: ifTrue: [ continuation value: aMessage arguments first ] ifFalse: [ receiver := objects at: aMessage receiver ifAbsent: [ ^ self ]. self handleInteractionDuring: [ receiver handleMessage: aMessage ] ]! ! !OBWebLink methodsFor: 'messaging' stamp: 'lr 11/7/2009 18:32'! escape ^ computation escape: [ :cc | continuation := cc ]! ! !OBWebLink methodsFor: 'messaging' stamp: 'lr 11/7/2009 18:32'! flushQueue | tmp | tmp := queue. self initializeQueue. ^ tmp! ! !OBWebLink methodsFor: 'notifications' stamp: 'cwp 10/30/2007 23:11'! handleAjaxResponse: response self queueMessage: response message. response resume! ! !OBWebLink methodsFor: 'notifications' stamp: 'lr 11/7/2009 18:32'! handleBrowseRequest: request | window | window := OBOpenWindowRequest for: request browser. self queueMessage: ((self createMessage) selector: #openWindow; arguments: {window path})! ! !OBWebLink methodsFor: 'notifications' stamp: 'lr 11/7/2009 18:32'! handleChoiceRequest: aRequest | message | message := self createMessage. message selector: 'requestChoice'; arguments: (Array with: aRequest prompt with: aRequest labels). self queueMessage: message. aRequest select: self escape! ! !OBWebLink methodsFor: 'notifications' stamp: 'lr 11/7/2009 18:32'! handleInformRequest: aRequest | message | message := self createMessage. message selector: 'inform'; arguments: (Array with: aRequest message). self queueMessage: message resuming: aRequest! ! !OBWebLink methodsFor: 'notifications' stamp: 'cwp 10/30/2007 22:04'! handleInteractionDuring: aBlock aBlock on: OBInteractionRequest do: [:response | response handleWith: self]. ! ! !OBWebLink methodsFor: 'notifications' stamp: 'lr 11/7/2009 18:32'! handleMenuRequest: aRequest | selection | self queueMessage: (aRequest messageWithReceiver: root identifier). selection := self escape. self handleInteractionDuring: [ aRequest select: selection ]! ! !OBWebLink methodsFor: 'notifications' stamp: 'lr 11/7/2009 18:32'! handleTextRequest: aRequest | message | message := self createMessage. message selector: 'requestText'; arguments: (Array with: aRequest prompt with: aRequest template). self queueMessage: message resuming: aRequest! ! !OBWebLink methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initialize mutex := Semaphore forMutualExclusion. self initializeQueue! ! !OBWebLink methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initializeQueue queue := SortedCollection sortBlock: [ :a :b | b priority <= a priority ]! ! !OBWebLink methodsFor: 'messaging' stamp: 'lr 11/7/2009 18:32'! processMessage: aMessage ^ mutex critical: [ OBSubcomputation do: [ :escape | computation := escape. self deliverMessage: aMessage ]. self flushQueue ]! ! !OBWebLink methodsFor: 'messaging' stamp: 'cwp 10/30/2007 23:11'! queueMessage: anAjaxMessage (queue noneSatisfy: [:ea | anAjaxMessage isDuplicateOf: ea]) ifTrue: [queue add: anAjaxMessage]! ! !OBWebLink methodsFor: 'messaging' stamp: 'lr 11/7/2009 18:32'! queueMessage: anAjaxMessage resuming: aRequest | value | self queueMessage: anAjaxMessage. value := computation escape: [ :cc | continuation := cc ]. aRequest resume: value! ! Object subclass: #OBWebMenuItem instanceVariableNames: 'label target selector arguments isEnabled' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebMenuItem class methodsFor: 'as yet unclassified' stamp: 'cwp 10/8/2007 01:55'! label: aString enabled: aBoolean submenu: aMenu | item | item := self basicNew. item setLabel: aString target: aMenu selector: #open arguments: #(). item isEnabled: aBoolean. ^item! ! !OBWebMenuItem class methodsFor: 'as yet unclassified' stamp: 'cwp 5/24/2007 23:54'! label: aString target: anObject selector: aSymbol ^ self label: aString target: anObject selector: aSymbol arguments: Array new.! ! !OBWebMenuItem class methodsFor: 'as yet unclassified' stamp: 'cwp 5/24/2007 23:54'! label: aString target: anObject selector: aSymbol arguments: anArray ^ self basicNew setLabel: aString target: anObject selector: aSymbol arguments: anArray.! ! !OBWebMenuItem class methodsFor: 'as yet unclassified' stamp: 'cwp 6/11/2007 00:48'! label: aString target: anObject selector: aSymbol isEnabled: aBoolean ^ (self basicNew setLabel: aString target: anObject selector: aSymbol arguments: Array new) isEnabled: aBoolean; yourself! ! !OBWebMenuItem methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! isEnabled: aBoolean isEnabled := aBoolean! ! !OBWebMenuItem methodsFor: 'as yet unclassified' stamp: 'cwp 5/25/2007 00:29'! jsonWriteOn: aStream aStream nextPut: ${; jsonPrint: 'label'; nextPutAll: ': '; jsonPrint: label; nextPutAll: ', '; jsonPrint: 'isEnabled'; nextPutAll: ': '; jsonPrint: isEnabled; nextPut: $}! ! !OBWebMenuItem methodsFor: 'as yet unclassified' stamp: 'cwp 5/25/2007 23:02'! label ^ label! ! !OBWebMenuItem methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! setLabel: aString target: anObject selector: aSymbol arguments: anArray label := aString. target := anObject. selector := aSymbol. arguments := anArray. isEnabled := true! ! !OBWebMenuItem methodsFor: 'as yet unclassified' stamp: 'cwp 5/25/2007 23:10'! value target perform: selector withArguments: arguments! ! Object subclass: #OBWebWidget instanceVariableNames: 'id model children' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! OBWebWidget subclass: #OBWebChoiceWidget instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! OBWebChoiceWidget subclass: #OBWebButtonBar instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebButtonBar methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 11:45'! htmlClass ^ 'ButtonBar vertical'! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'cwp 5/21/2007 23:03'! allowedSelectors ^ #(select:)! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'cwp 5/21/2007 23:03'! jsInitializeSelfOn: aStream self jsWidgetAccessorOn: aStream. aStream nextPutAll: '.update('; jsonPrint: self state; nextPutAll: ');'! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'cwp 5/21/2007 23:04'! list ^ model list ! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! select: aString | index | index := self list indexOf: aString. model selection: index! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! selection | selection | selection := model selection. ^ selection = 0 ifTrue: [ nil ] ifFalse: [ selection - 1 ]! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'cwp 5/21/2007 23:05'! state ^ JsonObject new items: self list; selection: self selection; yourself! ! !OBWebChoiceWidget methodsFor: 'as yet unclassified' stamp: 'cwp 5/21/2007 23:05'! update: aSelector self sendUpdate! ! OBWebChoiceWidget subclass: #OBWebList instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebList methodsFor: 'accessing' stamp: 'cwp 5/24/2007 01:04'! allowedSelectors ^ super allowedSelectors, #(openMenu)! ! !OBWebList methodsFor: 'html' stamp: 'cwp 10/25/2006 11:45'! htmlClass ^ 'List vertical'! ! !OBWebList methodsFor: 'callbacks' stamp: 'lr 11/7/2009 18:32'! openMenu | menu | menu := OBWebMenu new. model menu: menu. menu open! ! !OBWebList methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! state | list icons first | list := self list. icons := list size > 0 ifFalse: [ #() ] ifTrue: [ first := model iconAt: 1. first ifNil: [ #() ] ifNotNil: [ ((2 to: list size) collect: [ :i | model iconAt: i ]) copyWithFirst: first ] ]. ^ (JsonObject new) items: list; icons: icons; selection: self selection; yourself! ! OBWebWidget subclass: #OBWebMenu instanceVariableNames: 'items' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebMenu class methodsFor: 'as yet unclassified' stamp: 'cwp 5/25/2007 00:36'! seed: anInteger ^ self basicNew initializeWithId: (OBWebIdentifier seed: anInteger)! ! !OBWebMenu methodsFor: 'compatibility' stamp: 'cwp 6/24/2007 18:20'! add: aString action: aSymbol "Evil hack, but just ignore items added in this way"! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 5/24/2007 23:53'! add: aString target: anObject selector: aSymbol items add: (OBWebMenuItem label: aString target: anObject selector: aSymbol)! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 6/11/2007 00:46'! add: aString target: anObject selector: aSymbol enabled: aBoolean icon: ignored items add: (OBWebMenuItem label: aString target: anObject selector: aSymbol isEnabled: aBoolean)! ! !OBWebMenu methodsFor: 'compatibility' stamp: 'cwp 5/24/2007 23:58'! addBlankIconsIfNecessary: anObject ! ! !OBWebMenu methodsFor: 'compatibility' stamp: 'cwp 5/24/2007 23:59'! addLine items add: nil! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 10/8/2007 01:55'! addSubmenu: aString enabled: aBoolean | submenu | submenu := self class new. items add: (OBWebMenuItem label: aString enabled: aBoolean submenu: submenu). ^submenu! ! !OBWebMenu methodsFor: 'accessing' stamp: 'cwp 5/25/2007 22:59'! allowedSelectors ^ #(select:)! ! !OBWebMenu methodsFor: 'printing' stamp: 'cwp 5/25/2007 22:06'! htmlTagOn: aStream ! ! !OBWebMenu methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initializeWithId: aWebId super initializeWithId: aWebId. items := OrderedCollection new! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 5/24/2007 23:42'! items ^ items! ! !OBWebMenu methodsFor: 'printing' stamp: 'cwp 5/25/2007 00:48'! jsonWriteOn: aStream JsonObject new id: id asString; items: items; jsonWriteOn: aStream! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 5/24/2007 23:56'! lastItem ^ items size >= 1 ifTrue: [items last]! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 10/8/2007 02:04'! open self simplify. OBMenuRequest for: self! ! !OBWebMenu methodsFor: 'callbacks' stamp: 'lr 11/7/2009 18:32'! select: aString | item | item := items detect: [ :ea | ea ifNil: [ false ] ifNotNil: [ ea label = aString ] ] ifNone: [ ^ self ]. item value! ! !OBWebMenu methodsFor: 'building' stamp: 'cwp 6/7/2009 01:02'! simplify items ifEmpty: [^ self]. [items first isNil] whileTrue: [items removeFirst]. [items last isNil] whileTrue: [items removeLast].! ! OBWebWidget subclass: #OBWebPane instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebPane methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 00:46'! asJson ^ JsonObject new id: self identifier; list: children first identifier; buttons: children second identifier; show: model wantsButton; yourself! ! !OBWebPane methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 11:45'! htmlClass ^ 'Pane horizontal'! ! !OBWebPane methodsFor: 'as yet unclassified' stamp: 'cwp 5/22/2007 00:08'! jsInitializeSelfOn: aStream self jsWidgetAccessorOn: aStream. model wantsButton ifTrue: [aStream nextPutAll: '.showSwitch();'] ifFalse: [aStream nextPutAll: '.hideSwitch();']! ! !OBWebPane methodsFor: 'as yet unclassified' stamp: 'cwp 5/22/2007 00:15'! state ^ model wantsButton! ! !OBWebPane methodsFor: 'as yet unclassified' stamp: 'cwp 5/22/2007 00:14'! update: aSelector aSelector = #switch ifTrue: [self sendUpdate]! ! OBWebWidget subclass: #OBWebScroller instanceVariableNames: 'sizing' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 02:00'! basicUpdateSizing model ifNil: [sizing := 1] ifNotNil: [sizing := model sizing]! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 10/25/2006 11:44'! htmlClass ^ 'Scroller vertical'! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 9/11/2007 23:59'! htmlStyle ^ 'top: 0%; bottom: 60%'! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 01:55'! jsInitializeSelfOn: aStream self jsWidgetAccessorOn: aStream. aStream nextPutAll: '.setSizing('; jsonPrint: model sizing; nextPutAll: ');'! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 00:42'! pop: count count timesRepeat: [children removeLast]. self sendPop: count! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! push: columns | pane | columns doWithIndex: [ :col :index | pane := OBWebBuilder build: col. self addChild: pane. self sendPush: pane priority: columns size - index + 1 ]! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 00:43'! sendPop: count self createMessage selector: #pop; arguments: {count}; queue! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 00:44'! sendPush: aPane priority: anInteger self createMessage selector: #push; arguments: {aPane asJson}; priority: anInteger; queue! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 01:59'! sizing ^ sizing ifNil: [self basicUpdateSizing]! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/27/2007 20:45'! state ^ children collect: [:ea | ea identifier]! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'cwp 5/28/2007 01:57'! update: aSymbol aSymbol = #columns ifTrue: [self updatePanes]! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! updatePanes | columns | columns := model columns. columns size > children size ifTrue: [ self push: (columns allButFirst: children size) ] ifFalse: [ columns size < children size ifTrue: [ self pop: children size - columns size ] ]. self updateSizing! ! !OBWebScroller methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! updateSizing | old | old := sizing. self basicUpdateSizing. sizing = old ifFalse: [ (self createMessage) selector: #setSizing; arguments: {sizing}; queue ]! ! OBWebWidget subclass: #OBWebText instanceVariableNames: 'text' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebText methodsFor: 'view callbacks' stamp: 'lr 11/7/2009 18:32'! accept: aString text := aString asText. model accept: text notifying: self! ! !OBWebText methodsFor: 'accessing' stamp: 'cwp 6/20/2007 21:41'! allowedSelectors ^ #(accept: menuShifted:selection: implementors: senders: references: browse:)! ! !OBWebText methodsFor: 'view callbacks' stamp: 'cwp 6/17/2007 18:33'! browse: aString model browseIt: aString findSelector! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 23:12'! correctFrom: start to: end with: aString self text replaceFrom: start to: end with: aString. self sendUpdate. ^ text! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 19:41'! deselect ! ! !OBWebText methodsFor: 'accessing' stamp: 'cwp 10/25/2006 11:45'! htmlClass ^ 'Text vertical'! ! !OBWebText methodsFor: 'html' stamp: 'cwp 9/11/2007 23:59'! htmlStyle ^ 'top: 40%; bottom: 0%'! ! !OBWebText methodsFor: 'view callbacks' stamp: 'cwp 6/16/2007 23:56'! implementors: aString model implementorsOfIt: aString findSelector! ! !OBWebText methodsFor: 'html' stamp: 'cwp 6/2/2007 02:02'! jsInitializeSelfOn: aStream self jsWidgetAccessorOn: aStream. aStream nextPutAll: '.init('; jsonPrint: self state; nextPutAll: ');'! ! !OBWebText methodsFor: 'view callbacks' stamp: 'lr 11/7/2009 18:32'! menuShifted: aBoolean selection: aString | menu selection | selection := OBTextSelection onAllOf: aString. menu := OBWebMenu new. model menu: menu shifted: aBoolean selection: selection. menu open! ! !OBWebText methodsFor: 'model callbacks' stamp: 'lr 11/7/2009 18:32'! notify: aString at: anInteger in: aReadStream text := Text streamContents: [ :stream | 1 to: anInteger - 1 do: [ :i | stream nextPut: (text at: i) ]. stream nextPutAll: aString. anInteger to: text size do: [ :i | stream nextPut: (text at: i) ] ]. self sendUpdate! ! !OBWebText methodsFor: 'view callbacks' stamp: 'cwp 6/17/2007 18:32'! references: aString model referencesToIt: aString findSelector! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 19:40'! select ! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 19:39'! selectFrom: aSmallInteger to: aSmallInteger2 ! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 19:42'! selectInvisiblyFrom: aSmallInteger to: aSmallInteger2 ! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 19:39'! selectionInterval ^ 1 to: 0! ! !OBWebText methodsFor: 'view callbacks' stamp: 'cwp 6/17/2007 18:32'! senders: aString model sendersOfIt: aString findSelector! ! !OBWebText methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! state | bold | bold := self text isText and: [ (self text rangeOf: TextEmphasis bold startingAt: 1) size > 0 ]. ^ (JsonObject new) text: self text; bold: bold; yourself! ! !OBWebText methodsFor: 'model callbacks' stamp: 'cwp 10/16/2007 23:10'! text ^ text ifNil: ['' asText]! ! !OBWebText methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! update: aSelector text := model text. self sendUpdate! ! !OBWebWidget class methodsFor: 'as yet unclassified' stamp: 'cwp 10/24/2006 14:44'! id: aWebIdentifier model: anObject ^ (self basicNew initializeWithId: aWebIdentifier) model: anObject; yourself! ! !OBWebWidget class methodsFor: 'as yet unclassified' stamp: 'cwp 10/22/2006 02:10'! model: aBrowser ^ self new model: aBrowser! ! !OBWebWidget class methodsFor: 'as yet unclassified' stamp: 'cwp 10/22/2006 02:10'! new ^ self basicNew initialize! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/25/2006 19:08'! addAllChildrenTo: aDictionary children do: [:ea | ea addWithAllChildrenTo: aDictionary]. ^ aDictionary! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/22/2006 02:09'! addChild: aWidget children add: aWidget! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/25/2006 19:08'! addWithAllChildrenTo: aDictionary aDictionary at: self identifier put: self. ^ self addAllChildrenTo: aDictionary. ! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/25/2006 19:20'! allChildren ^ self addAllChildrenTo: (Dictionary new)! ! !OBWebWidget methodsFor: 'accessing' stamp: 'cwp 10/25/2006 21:38'! allowedSelectors ^ #()! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/22/2006 01:50'! children ^ children! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 10/10/2007 00:00'! contentType ^ 'text/html'! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 10/9/2007 23:59'! contents ^ String streamContents: [:s | self htmlOn: s]! ! !OBWebWidget methodsFor: 'accessing' stamp: 'cwp 10/27/2006 00:26'! createMessage ^ OBAjaxMessage receiver: self identifier! ! !OBWebWidget methodsFor: 'ajax' stamp: 'lr 11/7/2009 18:32'! handleMessage: message | selector | selector := message selector asSymbol. ^ (self allowedSelectors includes: selector) ifTrue: [ self perform: selector withArguments: message arguments. true ] ifFalse: [ false ]! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 10/24/2006 15:31'! htmlStyle ^ nil! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 10/24/2006 15:31'! htmlTagOn: aStream aStream nextPutAll: '
. children do: [:ea | ea htmlTagOn: aStream]. aStream nextPutAll: '
'! ! !OBWebWidget methodsFor: 'accessing' stamp: 'cwp 10/22/2006 01:49'! identifier ^ id asString! ! !OBWebWidget methodsFor: 'initialize-release' stamp: 'cwp 10/24/2006 14:31'! initialize self initializeWithId: (OBWebIdentifier new)! ! !OBWebWidget methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initializeWithId: aWebIdentifier id := aWebIdentifier. children := OrderedCollection new! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 6/12/2007 21:19'! jsInitializeOn: aStream self jsInitializeSelfOn: aStream. aStream space. children do: [:ea | ea jsInitializeOn: aStream] separatedBy: [aStream space]! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 5/21/2007 00:25'! jsInitializeSelfOn: aStream ! ! !OBWebWidget methodsFor: 'html' stamp: 'cwp 10/25/2006 12:03'! jsWidgetAccessorOn: aStream aStream nextPutAll: 'Widget.get("'; print: id; nextPutAll: '")'! ! !OBWebWidget methodsFor: 'accessing' stamp: 'cwp 10/22/2006 01:49'! model ^ model! ! !OBWebWidget methodsFor: 'accessing' stamp: 'lr 11/7/2009 18:32'! model: anObject model ifNotNil: [ model removeDependent: self ]. anObject ifNotNil: [ anObject addDependent: self ]. model := anObject! ! !OBWebWidget methodsFor: 'initialize-release' stamp: 'cwp 10/25/2006 13:42'! registerWith: aHttpService aHttpService addResponder: self. children do: [:ea | ea registerWith: aHttpService]! ! !OBWebWidget methodsFor: 'ajax' stamp: 'cwp 5/21/2007 00:13'! sendUpdate self createMessage selector: #update; arguments: [Array with: self state]; queue! ! !OBWebWidget methodsFor: 'accessing' stamp: 'cwp 10/27/2006 00:11'! update: aSelector Transcript cr; show: self class name, ': ', aSelector! ! !OBWebWidget methodsFor: 'children' stamp: 'cwp 10/25/2006 19:20'! withAllChildren ^ self addWithAllChildrenTo: Dictionary new! ! OBWebWidget subclass: #OBWebWindow instanceVariableNames: 'queue continuation link' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Widgets'! !OBWebWindow methodsFor: 'accessing' stamp: 'cwp 10/31/2007 01:41'! addChild: aWidget super addChild: aWidget. aWidget addWithAllChildrenTo: link! ! !OBWebWindow methodsFor: 'accessing' stamp: 'cwp 10/28/2007 21:19'! allowedSelectors ^ #(close ping)! ! !OBWebWindow methodsFor: 'callbacks' stamp: 'cwp 5/31/2007 00:08'! close model windowIsClosing. OBCloseWindowRequest for: self! ! !OBWebWindow methodsFor: 'accessing' stamp: 'cwp 10/27/2006 01:00'! htmlClass ^ 'Root root'! ! !OBWebWindow methodsFor: 'html' stamp: 'cwp 8/2/2007 01:34'! htmlOn: aStream aStream nextPutAll: 'browser'. self htmlTagOn: aStream. aStream nextPutAll: ''; nextPutAll: '' ! ! !OBWebWindow methodsFor: 'initialize-release' stamp: 'lr 11/7/2009 18:32'! initializeQueue queue := SortedCollection sortBlock: [ :a :b | b priority <= a priority ]! ! !OBWebWindow methodsFor: 'initialize-release' stamp: 'cwp 10/31/2007 01:38'! initializeWithId: aWebIdentifier super initializeWithId: aWebIdentifier. link := OBWebLink new. link at: self identifier put: self. self initializeQueue! ! !OBWebWindow methodsFor: 'html' stamp: 'cwp 6/18/2007 18:53'! jsInitializeSelfOn: aStream aStream nextPutAll: 'Widget.init("'; print: id; nextPutAll: '");'. ! ! !OBWebWindow methodsFor: 'accessing' stamp: 'cwp 10/10/2007 00:35'! path ^ '/windows/', self identifier! ! !OBWebWindow methodsFor: 'callbacks' stamp: 'cwp 10/29/2007 00:55'! ping ! ! !OBWebWindow methodsFor: 'messaging' stamp: 'cwp 10/31/2007 01:55'! processMessage: aMessage ^ link processMessage: aMessage! ! !OBWebWindow methodsFor: 'accessing' stamp: 'cwp 10/27/2006 01:01'! update: aSelector aSelector = #relabel ifTrue: [self createMessage selector: 'title'; arguments: {model labelString}; queue]! ! !Dictionary methodsFor: '*ob-web' stamp: 'lr 11/7/2009 18:42'! resolvePath: aCollection ifAbsent: aBlock | head tail child | head := aCollection first. tail := aCollection allButFirst. child := self at: head ifAbsent: aBlock. ^ tail isEmpty ifTrue: [ child ] ifFalse: [ child resolvePath: tail ifAbsent: aBlock ]! ! OBInteractionRequest subclass: #OBAjaxResponse instanceVariableNames: 'message' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Core'! !OBAjaxResponse class methodsFor: 'as yet unclassified' stamp: 'cwp 5/27/2007 22:39'! message: aMessage ^ self basicNew setMessage: aMessage! ! !OBAjaxResponse methodsFor: 'as yet unclassified' stamp: 'cwp 5/25/2007 22:57'! handleWith: anObject ^ anObject handleAjaxResponse: self! ! !OBAjaxResponse methodsFor: 'as yet unclassified' stamp: 'cwp 10/26/2006 20:56'! message ^ message! ! !OBAjaxResponse methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! setMessage: anAjaxMessage message := anAjaxMessage! ! OBInteractionRequest subclass: #OBMenuRequest instanceVariableNames: 'menu' classVariableNames: '' poolDictionaries: '' category: 'OB-Web-Notifications'! !OBMenuRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 10/8/2007 02:04'! for: aMenu (self basicNew setMenu: aMenu) signal! ! !OBMenuRequest methodsFor: 'as yet unclassified' stamp: 'cwp 6/19/2007 23:28'! handleWith: anObject ^ anObject handleMenuRequest: self! ! !OBMenuRequest methodsFor: 'as yet unclassified' stamp: 'cwp 6/19/2007 23:11'! menu ^ menu! ! !OBMenuRequest methodsFor: 'as yet unclassified' stamp: 'cwp 10/8/2007 02:03'! messageWithReceiver: aString ^ (OBAjaxMessage receiver: aString) selector: #openMenu; arguments: (Array with: menu); yourself! ! !OBMenuRequest methodsFor: 'as yet unclassified' stamp: 'cwp 6/19/2007 23:17'! select: anInteger menu select: anInteger! ! !OBMenuRequest methodsFor: 'as yet unclassified' stamp: 'lr 11/7/2009 18:32'! setMenu: aMenu menu := aMenu! ! OBKomHttpService initialize! OBWebIcons initialize!