diff --git a/stitchcode/blocks.js b/stitchcode/blocks.js new file mode 100644 index 00000000..c26c86f9 --- /dev/null +++ b/stitchcode/blocks.js @@ -0,0 +1,263 @@ +SymbolMorph.prototype.names.push('largeStage'); + +SymbolMorph.prototype.originalSymbolCanvasColored = SymbolMorph.prototype.symbolCanvasColored; +SymbolMorph.prototype.symbolCanvasColored = function (aColor) { + if (this.name == 'largeStage') { + return this.drawSymbolLargeStage(newCanvas(new Point(this.symbolWidth(), this.size)), aColor); + } else { + return this.originalSymbolCanvasColored(aColor) + } +} + +SymbolMorph.prototype.drawSymbolFullScreen = function (canvas, color) { + // answer a canvas showing two arrows pointing diagonally outwards + var ctx = canvas.getContext('2d'), + h = canvas.height, + c = canvas.width / 2, + off = canvas.width / 10, + w = canvas.width / 2; + + ctx.strokeStyle = color.toString(); + ctx.lineWidth = 1.5; + ctx.moveTo(c - off, c + off); + ctx.lineTo(0, h); + ctx.stroke(); + + ctx.moveTo(c + off, c - off); + ctx.lineTo(h, 0); + ctx.stroke(); + + ctx.moveTo(0, h); + ctx.lineTo(0, h - w); + ctx.stroke(); + ctx.moveTo(0, h); + ctx.lineTo(w, h); + ctx.stroke(); + + ctx.moveTo(h, 0); + ctx.lineTo(h - w, 0); + ctx.stroke(); + ctx.moveTo(h, 0); + ctx.lineTo(h, w); + ctx.stroke(); + + return canvas; +}; + +SymbolMorph.prototype.drawSymbolFile= function (canvas, color) { + // answer a canvas showing a page symbol + var ctx = canvas.getContext('2d'), + w = Math.min(canvas.width, canvas.height) / 2; + + //ctx.fillStyle = color.toString(); + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(w, 0); + ctx.lineTo(w, w); + ctx.lineTo(canvas.width, w); + ctx.lineTo(canvas.width, canvas.height); + ctx.lineTo(0, canvas.height); + ctx.stroke(); + //ctx.fill(); + + //ctx.fillStyle = color.darker(25).toString(); + ctx.beginPath(); + ctx.moveTo(w, 0); + ctx.lineTo(canvas.width, w); + ctx.lineTo(w, w); + ctx.lineTo(w, 0); + ctx.stroke(); + //ctx.fill(); + + return canvas; +}; + +SymbolMorph.prototype.drawSymbolNormalScreen = function (canvas, color) { + // answer a canvas showing two arrows pointing diagonally outwards + var ctx = canvas.getContext('2d'), + h = canvas.height, + c = canvas.width / 2, + off = canvas.width / 10, + w = canvas.width / 2; + + ctx.strokeStyle = color.toString(); + ctx.lineWidth = 1.5; + ctx.moveTo(c - off, c + off); + ctx.lineTo(0, h); + ctx.stroke(); + + ctx.moveTo(c + off, c - off); + ctx.lineTo(h, 0); + ctx.stroke(); + + ctx.moveTo(0, h); + ctx.lineTo(0, h - w); + ctx.stroke(); + ctx.moveTo(0, h); + ctx.lineTo(w, h); + ctx.stroke(); + + ctx.moveTo(h, 0); + ctx.lineTo(h - w, 0); + ctx.stroke(); + ctx.moveTo(h, 0); + ctx.lineTo(h, w); + ctx.stroke(); + + return canvas; +}; + + +SymbolMorph.prototype.drawSymbolLargeStage = function (canvas, color) { + var ctx = canvas.getContext('2d'), + w = canvas.width, + h = canvas.height, + w2 = w * 1 / 3, + h2 = h * 2 / 3; + + ctx.strokeStyle = color.toString(); + ctx.lineWidth = 2; + ctx.rect(0, 0, w, h); + ctx.stroke(); + ctx.rect(w2, 0, w, h2); + ctx.stroke(); + + return canvas; +}; + +SymbolMorph.prototype.drawSymbolNormalStage = function (canvas, color) { + var ctx = canvas.getContext('2d'), + w = canvas.width, + h = canvas.height, + w2 = w / 2, + h2 = h / 2; + + ctx.strokeStyle = color.toString(); + ctx.lineWidth = 2; + ctx.rect(0, 0, w, h); + ctx.stroke(); + ctx.rect(w2, 0, w2, h2); + ctx.stroke(); + + return canvas; +}; + +SymbolMorph.prototype.drawSymbolSmallStage = function (canvas, color) { + var ctx = canvas.getContext('2d'), + w = canvas.width, + h = canvas.height, + w2 = w * 2 / 3, + h2 = h * 1 / 3; + + ctx.strokeStyle = color.toString(); + ctx.lineWidth = 2; + ctx.rect(0, 0, w, h); + ctx.stroke(); + ctx.rect(w2, 0, w2, h2); + ctx.stroke(); + + return canvas; +}; + +SymbolMorph.prototype.originalSymbolWidth = SymbolMorph.prototype.symbolWidth; +SymbolMorph.prototype.symbolWidth = function () { + switch (this.name) { + case 'gears': + case 'file': + return this.originalSymbolWidth() * 2; + default: + return this.originalSymbolWidth(); + } +}; + +SymbolMorph.prototype.drawSymbolGears = function (canvas, color) { + // overriden to add a small triangle to its right + var ctx = canvas.getContext('2d'), + w = canvas.width / 2, + r = w / 2, + e = w / 6, + triangleX = w * 7/6; + + ctx.strokeStyle = color.toString(); + ctx.fillStyle = color.toString(); + ctx.lineWidth = canvas.height / 7; + + ctx.beginPath(); + ctx.arc(r, r, e * 1.5, radians(0), radians(360)); + ctx.fill(); + + + ctx.moveTo(0, r); + ctx.lineTo(w, r); + ctx.stroke(); + + ctx.moveTo(r, 0); + ctx.lineTo(r, w); + ctx.stroke(); + + ctx.moveTo(e, e); + ctx.lineTo(w - e, w - e); + ctx.stroke(); + + ctx.moveTo(w - e, e); + ctx.lineTo(e, w - e); + ctx.stroke(); + + ctx.globalCompositeOperation = 'destination-out'; + + ctx.beginPath(); + ctx.arc(r, r, e * 1.5, radians(0), radians(360), true); + ctx.fill(); + + ctx.globalCompositeOperation = 'source-over'; + + // triangle + ctx.beginPath(); + ctx.moveTo(triangleX + 1, canvas.height / 5 * 2); + ctx.lineTo(triangleX + 1 + (canvas.width - triangleX - 2) / 2, canvas.height / 5 * 4); + ctx.lineTo(canvas.width - 1, canvas.height / 5 * 2); + ctx.lineTo(triangleX + 1, canvas.height / 5 * 2); + ctx.closePath(); + ctx.fill(); + + return canvas; +}; + +SymbolMorph.prototype.drawSymbolFile = function (canvas, color) { + // overriden to add a small triangle to its right + var ctx = canvas.getContext('2d'), + w = canvas.width / 4, + maxW = canvas.width / 2; + + ctx.fillStyle = color.toString(); + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(w, 0); + ctx.lineTo(w, w); + ctx.lineTo(maxW, w); + ctx.lineTo(maxW, canvas.height); + ctx.lineTo(0, canvas.height); + ctx.closePath(); + ctx.fill(); + + ctx.fillStyle = color.darker(25).toString(); + ctx.beginPath(); + ctx.moveTo(w, 0); + ctx.lineTo(maxW, w); + ctx.lineTo(w, w); + ctx.lineTo(w, 0); + ctx.closePath(); + ctx.fill(); + + // triangle + ctx.beginPath(); + ctx.moveTo(maxW + 2, canvas.height / 5 * 2); + ctx.lineTo(maxW + 2 + (canvas.width - maxW - 2) / 2, canvas.height / 5 * 4); + ctx.lineTo(canvas.width, canvas.height / 5 * 2); + ctx.lineTo(maxW + 2, canvas.height / 5 * 2); + ctx.closePath(); + ctx.fill(); + + return canvas; +} +; diff --git a/stitchcode/gui-cloud.js b/stitchcode/gui-cloud.js new file mode 100644 index 00000000..06c7dc3f --- /dev/null +++ b/stitchcode/gui-cloud.js @@ -0,0 +1,362 @@ +IDE_Morph.prototype.openIn = function (world) { + var hash, usr, myself = this, urlLanguage = null; + + // get persistent user data, if any + if (localStorage) { + usr = localStorage['-snap-user']; + if (usr) { + usr = SnapCloud.parseResponse(usr)[0]; + if (usr) { + SnapCloud.username = usr.username || null; + SnapCloud.password = usr.password || null; + if (SnapCloud.username) { + this.source = 'cloud'; + } + } + } + } + + SnapCloud.isloggedin(function () + { + str = SnapCloud.encodeDict( + { + username: SnapCloud.username + } + ); + localStorage['-snap-user'] = str; + myself.source = 'cloud'; + myself.showMessage('now connected.', 2); + }, myself.cloudError() + ); + + this.buildPanes(); + world.add(this); + world.userMenu = this.userMenu; + + // override SnapCloud's user message with Morphic + SnapCloud.message = function (string) { + var m = new MenuMorph(null, string), + intervalHandle; + m.popUpCenteredInWorld(world); + intervalHandle = setInterval(function () { + m.destroy(); + clearInterval(intervalHandle); + }, 2000); + }; + + // prevent non-DialogBoxMorphs from being dropped + // onto the World in user-mode + world.reactToDropOf = function (morph) { + if (!(morph instanceof DialogBoxMorph)) { + if (world.hand.grabOrigin) { + morph.slideBackTo(world.hand.grabOrigin); + } else { + world.hand.grab(morph); + } + } + }; + + this.reactToWorldResize(world.bounds); + + function getURL(url) { + try { + var request = new XMLHttpRequest(); + request.open('GET', url, false); + request.send(); + if (request.status === 200) { + return request.responseText; + } + throw new Error('unable to retrieve ' + url); + } catch (err) { + myself.showMessage('unable to retrieve project'); + return ''; + } + } + + // dynamic notifications from non-source text files + // has some issues, commented out for now + /* + this.cloudMsg = getURL('http://snap.berkeley.edu/cloudmsg.txt'); + motd = getURL('http://snap.berkeley.edu/motd.txt'); + if (motd) { + this.inform('Snap!', motd); + } + */ + function interpretUrlAnchors() { + var dict; + if (location.hash.substr(0, 6) === '#open:') { + hash = location.hash.substr(6); + if (hash.charAt(0) === '%' + || hash.search(/\%(?:[0-9a-f]{2})/i) > -1) { + hash = decodeURIComponent(hash); + } + if (contains( + ['project', 'blocks', 'sprites', 'snapdata'].map( + function (each) { + return hash.substr(0, 8).indexOf(each); + } + ), + 1 + )) { + this.droppedText(hash); + } else { + this.droppedText(getURL(hash)); + } + } else if (location.hash.substr(0, 5) === '#run:') { + hash = location.hash.substr(5); + if (hash.charAt(0) === '%' + || hash.search(/\%(?:[0-9a-f]{2})/i) > -1) { + hash = decodeURIComponent(hash); + } + if (hash.substr(0, 8) === '') { + this.rawOpenProjectString(hash); + } else { + this.rawOpenProjectString(getURL(hash)); + } + this.toggleAppMode(true); + this.runScripts(); + } else if (location.hash.substr(0, 9) === '#present:') { + this.shield = new Morph(); + this.shield.color = this.color; + this.shield.setExtent(this.parent.extent()); + this.parent.add(this.shield); + myself.showMessage('Fetching project\nfrom the cloud...'); + + // make sure to lowercase the username + dict = SnapCloud.parseDict(location.hash.substr(9)); + dict.Username = dict.Username.toLowerCase(); + + SnapCloud.getPublicProject( + SnapCloud.encodeDict(dict), + function (projectData) { + var msg; + myself.nextSteps([ + function () { + msg = myself.showMessage('Opening project...'); + }, + function () {nop(); }, // yield (bug in Chrome) + function () { + if (projectData.indexOf('