diff --git a/js/IO.js b/js/IO.js index b9a726c..5671e2f 100644 --- a/js/IO.js +++ b/js/IO.js @@ -90,20 +90,45 @@ IO.prototype.makeObjects = function() { runtime.stage.attach(runtime.scene); runtime.stage.attachPenLayer(runtime.scene); runtime.stage.loadSounds(); - - // Create the sprites - $.each(this.data.children, function(index, obj) { + // Create the sprites and watchers + function createObj(obj, sprite) { var newSprite; - if (!obj.cmd) { - newSprite = new Sprite(obj); - } else { - newSprite = new Reporter(obj); - runtime.reporters.push(newSprite); - } - runtime.sprites.push(newSprite); - newSprite.attach(runtime.scene); - if (!obj.cmd) + function createSprite(obj) { + var newSprite = new Sprite(obj); newSprite.loadSounds(); + return newSprite; + } + function createReporter(obj, sprite) { + var newSprite; + if (obj.listName) { // list + if (!(sprite===runtime.stage && !runtime.stage.lists[obj.listName])) { // for local lists, only if in sprite + newSprite = new List(obj, sprite.objName); + runtime.reporters.push(newSprite); + } + } else { + newSprite = new Reporter(obj); + runtime.reporters.push(newSprite); + } + return newSprite; + } + if (obj.objName) { // sprite + newSprite = createSprite(obj); + sprite = newSprite; + } else { + newSprite = createReporter(obj, sprite); + } + if (newSprite) { + runtime.sprites.push(newSprite); + newSprite.attach(runtime.scene); + } + } + $.each(this.data.children, function(index, obj) { + createObj(obj, runtime.stage); // create children of stage - sprites, watchers, and stage's lists + }); + $.each(runtime.sprites.filter(function(sprite){return sprite instanceof Sprite}), function(index, sprite) { // list of sprites + $.each(sprite.lists, function(index, list){ + createObj(list, sprite); // create local lists + }); }); }; diff --git a/js/Reporter.js b/js/Reporter.js index d92011b..79a83f1 100644 --- a/js/Reporter.js +++ b/js/Reporter.js @@ -119,3 +119,81 @@ Reporter.prototype.changeSlider = function() { var variable = $(this).attr('data-var'); target.variables[variable] = newValue; }; + +var List = function(data, sprite) { + this.contents = data.contents; + this.listName = data.listName; + + this.height = data.height; + this.width = data.width; + this.x = data.x; + this.y = data.y; + this.z = io.getCount(); + this.visible = data.visible; + + this.target = sprite; + +// this.isPersistent = data.isPersistent; + + this.el = null; // jQuery element for list + this.containerEl = null; + this.scrollbar = null; +}; + +List.prototype.attach = function(scene) { + this.el = $('
'); + this.el.append('
'+(this.target==='Stage'?'':this.target+' ')+this.listName); + var c = this.containerEl = $('
').appendTo(this.el).width(this.width-13).height(this.height-34); + var s = this.scrollbar = $('
').appendTo(this.el); + var sb = s.children('.list-scrollbar'); + sb.mousedown(function(e){ + if (e.which===1) $(this).data({scrolling:true,startY:e.pageY}); // left button + }); + $('body').mousemove(function(e){ + if (sb.data('scrolling')) { + var offset = parseInt(sb.css('top'))+e.pageY-sb.data('startY'); + if (offset < 0) { + offset = 0; + } + if (offset > c.height()-sb.height()) { + offset = c.height()-sb.height(); + } + sb.css('top',offset); + c.scrollTop(c.height()/sb.height()*offset); + } + }).mouseup(function(){ + if ($.hasData(sb[0],'scrolling')) sb.removeData(['scrolling','startY']); + }); +// this.el.append('
+'); // disabled because it doesn't do anything even in the original + this.el.append('
length: '+this.contents.length); + scene.append(this.el); + this.update(); + this.el.css('left', this.x); + this.el.css('top', this.y); + this.el.width(this.width); + this.el.height(this.height); + this.el.css('z-index', this.z); + this.el.css('display', this.visible ? 'inline-block' : 'none'); +}; + +List.prototype.update = function(){ + this.contents = findList(runtime.spriteNamed(this.target),this.listName); + + this.el.css('display', this.visible ? 'inline-block' : 'none'); + if (!this.visible) return; + + var c = this.containerEl.html(''); // so that it can be used inside the forEach + this.contents.forEach(function(val,i){ + $('
').appendTo(c).append('
'+(i+1),'
'+val); + }); + c.find('.list-index').width(c.find('.list-index').last().width()); + c.find('.list-item').width(c.width()-c.find('.list-index').width()-15); + var s = this.scrollbar.height(c.height()); + s.children('.list-scrollbar').height(s.height()/c[0].scrollHeight*s.height()).css('display', s.children('.list-scrollbar').height()===c.height() ? 'none' : 'inline-block'); + this.el.find('.list-length').text('length: '+this.contents.length); +}; + +List.prototype.updateLayer = function() { + this.el.css('z-index', this.z); +}; + diff --git a/js/primitives/VarListPrims.js b/js/primitives/VarListPrims.js index 065be7d..a8f734a 100644 --- a/js/primitives/VarListPrims.js +++ b/js/primitives/VarListPrims.js @@ -34,6 +34,8 @@ VarListPrims.prototype.addPrimsTo = function(primTable) { primTable['lineCountOfList:'] = this.primListLength; primTable['getLine:ofList:'] = this.primListGetLine; primTable['list:contains:'] = this.primListContains; + primTable['hideList:'] = this.primHideList; + primTable['showList:'] = this.primShowList; }; // Variable primitive implementations @@ -74,9 +76,9 @@ VarListPrims.prototype.primChangeVar = function(b) { }; VarListPrims.prototype.primHideVar = function(b) { - var targetVar = interp.arg(b, 0); + var targetVar = interp.arg(b, 0), targetSprite = interp.targetSprite().objName; for (var r = 0; r < runtime.reporters.length; r++) { - if (runtime.reporters[r].cmd == 'getVar:' && runtime.reporters[r].param == targetVar) { + if (runtime.reporters[r].cmd == 'getVar:' && runtime.reporters[r].param == targetVar && (runtime.reporters[r].target == targetSprite || runtime.reporters[r].target == 'Stage')) { runtime.reporters[r].visible = false; return; } @@ -84,9 +86,9 @@ VarListPrims.prototype.primHideVar = function(b) { }; VarListPrims.prototype.primShowVar = function(b) { - var targetVar = interp.arg(b, 0); + var targetVar = interp.arg(b, 0), targetSprite = interp.targetSprite().objName; for (var r = 0; r < runtime.reporters.length; r++) { - if (runtime.reporters[r].cmd == 'getVar:' && runtime.reporters[r].param == targetVar) { + if (runtime.reporters[r].cmd == 'getVar:' && runtime.reporters[r].param == targetVar && (runtime.reporters[r].target == targetSprite || runtime.reporters[r].target == 'Stage')) { runtime.reporters[r].visible = true; return; } @@ -96,7 +98,7 @@ VarListPrims.prototype.primShowVar = function(b) { // List primitive implementations // Take a list name and target sprite and return the JS list itself -var findList = function(targetSprite, listName) { +function findList(targetSprite, listName) { if (targetSprite == null) targetSprite = runtime.stage; if (listName in targetSprite.lists) { return targetSprite.lists[listName].contents; @@ -104,7 +106,7 @@ var findList = function(targetSprite, listName) { return runtime.stage.lists[listName].contents; } return null; -}; +} VarListPrims.prototype.primReadList = function(b) { var list = findList(interp.targetSprite(), interp.arg(b, 0)); @@ -181,3 +183,23 @@ VarListPrims.prototype.primListContains = function(b) { if (parseFloat(searchItem) == searchItem) searchItem = parseFloat(searchItem); return $.inArray(searchItem, list) > -1; }; + +VarListPrims.prototype.primHideList = function(b) { + var targetList = interp.arg(b, 0), targetSprite = interp.targetSprite().objName; + for (var r = 0; r < runtime.reporters.length; r++) { + if (runtime.reporters[r] instanceof List && runtime.reporters[r].listName == targetList && (runtime.reporters[r].target == targetSprite || runtime.reporters[r].target == 'Stage')) { + runtime.reporters[r].visible = false; + return; + } + } +}; + +VarListPrims.prototype.primShowList = function(b) { + var targetList = interp.arg(b, 0), targetSprite = interp.targetSprite().objName; + for (var r = 0; r < runtime.reporters.length; r++) { + if (runtime.reporters[r] instanceof List && runtime.reporters[r].listName == targetList && (runtime.reporters[r].target == targetSprite || runtime.reporters[r].target == 'Stage')) { + runtime.reporters[r].visible = true; + return; + } + } +}; diff --git a/player.css b/player.css index f72db80..f2b13ae 100644 --- a/player.css +++ b/player.css @@ -92,6 +92,95 @@ position: absolute; } +/* List watcher styles */ +.list { + float: left; + border-radius: 7px; + -webkit-border-radius: 7px; + -moz-border-radius: 7px; + border-style: solid; + border-color: gray; + border-width: 2px; + background-color: #C1C4C7; + padding-left: 3px; + font: bold 11px sans-serif; + position: absolute; +} + +.list .list-title { + padding-top: 2px; + text-align: center; + color: black; + font-weight: bold; + margin-bottom: 4px; +} + +.list .list-scrollbar-container { + float: right; + width: 10px; + position: relative; +} + +.list .list-scrollbar { + position: absolute; + top: 0px; + width: 10px; + background-color: #a8aaad; + border-radius: 10px; +} + +.list .list-index { + color: rgb(81, 81, 81); + float: left; + padding: 2px; + margin-top: 0px; + text-align: right; + font: bold 11px; +} + +.list .list-item { + float: right; + height: 16px; + overflow: hidden; + margin-bottom: 0px; + margin-right: 2px; + padding-top: 2px; + padding-left: 5px; + border-color: white; + border-style: solid; + border-width: 1px; + border-radius: 4px; + background-color: #cc5b22; + color: white; + word-wrap: break-word; + font: bolder 11px sans-serif; +} + +.list .list-add { + clear: both; + background-color: #dedede; + width: 12px; + height: 12px; + border-radius: 12px; + color: #707070; + font: bold 10px sans-serif; + text-align: center; + position: absolute; + bottom: 2px; + left: 2px; +} + +.list .list-length { + font-size: 10px; + font-weight: normal; + text-align: center; + color: black; + position: absolute; + bottom: 2px; + left: 0px; + right: 0px; +} + /* Say/think bubble styles */ .bubble-container { position: absolute; @@ -138,3 +227,4 @@ background: url(img/think-bottom.png) transparent no-repeat; } +