From 16e0fa27ed5e8a49845af5fe9e112a39a7850049 Mon Sep 17 00:00:00 2001 From: Forrest Oliphant Date: Fri, 28 Sep 2012 20:12:42 +0300 Subject: [PATCH] start of views, simple layers #98 --- src/iframework.js | 4 +- src/node-box-native-view.js | 2 + src/nodes/image-cam.js | 6 +- src/nodes/image-combine.js | 55 ------------- src/nodes/image.js | 2 - src/nodes/video-player.js | 1 + src/nodes/view-layers.js | 99 ++++++++++++++++++++++ src/nodes/view.js | 159 ++++++++++++++++++++++++++++++++++++ 8 files changed, 266 insertions(+), 62 deletions(-) delete mode 100644 src/nodes/image-combine.js create mode 100644 src/nodes/view-layers.js create mode 100644 src/nodes/view.js diff --git a/src/iframework.js b/src/iframework.js index 472d3c7..7681d10 100644 --- a/src/iframework.js +++ b/src/iframework.js @@ -351,8 +351,8 @@ $(function(){ var graphEl = this.$(".graph"); this.shownGraph.addNode({ "src": url, - "x": graphEl.scrollLeft() + graphEl.width()/2 - 100, - "y": graphEl.scrollTop() + graphEl.height()/2 - 100 + "x": Math.floor(graphEl.scrollLeft() + graphEl.width()/2) - 100, + "y": Math.floor(graphEl.scrollTop() + graphEl.height()/2) - 100 }); this.$(".addbyurlinput") .val("") diff --git a/src/node-box-native-view.js b/src/node-box-native-view.js index 804c1d0..dae0afb 100644 --- a/src/node-box-native-view.js +++ b/src/node-box-native-view.js @@ -53,12 +53,14 @@ $(function(){ // Do everything that will cause a redraw here }, _triggerRedraw: false, + _lastRedraw: 0, renderAnimationFrame: function (timestamp) { // Get a tick from GraphView.renderAnimationFrame() // this._valueChanged is set by NodeBox.receive() if (this._triggerRedraw) { this._triggerRedraw = false; this.redraw(timestamp); + this._lastRedraw = timestamp; } }, send: function (name, value) { diff --git a/src/nodes/image-cam.js b/src/nodes/image-cam.js index 8d84914..13d724c 100644 --- a/src/nodes/image-cam.js +++ b/src/nodes/image-cam.js @@ -200,7 +200,7 @@ $(function(){ this.resetSizes = false; } }, - _lastTime: 0, + _lastRedraw: 0, renderAnimationFrame: function (timestamp) { // Get a tick from GraphView.renderAnimationFrame() // this._valueChanged is set by NodeBox.receive() @@ -209,9 +209,9 @@ $(function(){ this.redraw(timestamp); } if (this._fps && this._ms) { - if (timestamp-this._lastTime >= this._ms) { + if (timestamp-this._lastRedraw >= this._ms) { this.drawFrame(); - this._lastTime = timestamp; + this._lastRedraw = timestamp; } } }, diff --git a/src/nodes/image-combine.js b/src/nodes/image-combine.js deleted file mode 100644 index 33181ed..0000000 --- a/src/nodes/image-combine.js +++ /dev/null @@ -1,55 +0,0 @@ -// extends src/nodes/image.js which extends src/node-box-native-view.js - -$(function(){ - - Iframework.NativeNodes["image-combine"] = Iframework.NativeNodes["image"].extend({ - - info: { - title: "image-combine", - description: "native module test" - }, - initializeModule: function(){ - - }, - inputimage: function (image) { - // This should happen in port eventually - switch(Iframework.util.type(image)) { - case "ImageData" : - this.context.putImageData(image, 0, 0); - break; - case "HTMLCanvasElement" : - this.context.drawImage(image, 0, 0); - break; - default : - break; - } - this.send("image", this.canvas); - }, - renderAnimationFrame: function () { - // - }, - inputbang: function (i) { - this.$(".info").append("! "); - this.send("bang", "!"); - }, - inputs: { - image: { - type: "image" - }, - bang: { - type: "bang" - } - }, - outputs: { - image: { - type: "image" - }, - bang: { - type: "bang" - } - } - - }); - - -}); diff --git a/src/nodes/image.js b/src/nodes/image.js index bf2c964..7a69100 100644 --- a/src/nodes/image.js +++ b/src/nodes/image.js @@ -22,8 +22,6 @@ $(function(){ self.popout(); }) ); - // Add refresh event - // this.events["click .refresh"] = "refresh"; this.canvas = document.createElement("canvas"); this.canvas.width = 500; diff --git a/src/nodes/video-player.js b/src/nodes/video-player.js index 6688370..5180dc1 100644 --- a/src/nodes/video-player.js +++ b/src/nodes/video-player.js @@ -162,6 +162,7 @@ $(function(){ this.drawFrame(); this.send("time", currentTime); this._lastTimeSent = currentTime; + this._lastRedraw = timestamp; } }, inputs: { diff --git a/src/nodes/view-layers.js b/src/nodes/view-layers.js new file mode 100644 index 0000000..1d380a8 --- /dev/null +++ b/src/nodes/view-layers.js @@ -0,0 +1,99 @@ +// extends src/nodes/image.js which extends src/node-box-native-view.js + +$(function(){ + + var template = + '
'+ + '
'; + + Iframework.NativeNodes["view-layers"] = Iframework.NativeNodes["view"].extend({ + + info: { + title: "layers", + description: "can get any of the canvases in the graph and make a stack of them" + }, + template: _.template(template), + events: { + "change .vis": "setVis" + }, + initializeModule: function(){ + // Hide old + $(this.canvas).hide(); + // Make list + var list = $('
    '); + $("canvas").each(function(i, canvas){ + var li = $('
  • ') + .text(canvas.id); + var vis = $('') + .data({ + "canvas": canvas, + "id": canvas.id.split("-")[1] + }); + li.append(vis); + list.append(li); + }); + list.sortable(); + this.$(".info").html(list); + }, + setVis: function(event){ + if (!this.visible) { + this.visible = {}; + } + var id = $(event.target).data("id"); + if (event.target.checked) { + // Show canvas to copy + if (!this.visible[id]) { + var vis = {}; + this.visible[id] = vis; + vis.nativeView = this.model.graph.get("nodes").get(id).view.Native; + vis.original = $(event.target).data("canvas"); + vis.copy = document.createElement("canvas"); + vis.copy.width = vis.original.width; + vis.copy.height = vis.original.height; + vis.copy.style.position = "absolute"; + vis.copy.style.top = 0; + vis.copy.style.left = 0; + vis.context = vis.copy.getContext("2d"); + vis.context.drawImage(vis.original, 0, 0); + vis.last = vis.nativeView._lastRedraw; + this.$(".layers").append(vis.copy); + } + } else { + // Kill canvas + if (this.visible[id]) { + this.$(this.visible[id].copy).remove(); + this.visible[id] = null; + } + } + console.log(this.visible); + }, + redraw: function(){ + // Called from NodeBoxNativeView.renderAnimationFrame() + }, + renderAnimationFrame: function (timestamp) { + // Get a tick from GraphView.renderAnimationFrame() + // this._valueChanged is set by NodeBox.receive() + if (this._triggerRedraw) { + this._triggerRedraw = false; + this.redraw(timestamp); + this._lastRedraw = timestamp; + } + for (var i in this.visible) { + var layer = this.visible[i]; + if (layer) { + if (layer.last !== layer.nativeView._lastRedraw) { + layer.context.drawImage(layer.original, 0, 0); + layer.last = layer.nativeView._lastRedraw; + } + } + } + }, + inputs: { + }, + outputs: { + } + + }); + + +}); diff --git a/src/nodes/view.js b/src/nodes/view.js new file mode 100644 index 0000000..37fe1ea --- /dev/null +++ b/src/nodes/view.js @@ -0,0 +1,159 @@ +// extends src/node-box-native-view.js + +$(function(){ + + var template = + // ''+ + '
    '; + + Iframework.NativeNodes["view"] = Iframework.NodeBoxNativeView.extend({ + + template: _.template(template), + initializeCategory: function() { + // Add popout button to box + var self = this; + this.model.view.$("button.remove") + .after( + $('') + .button({ icons: { primary: "icon-popup" }, text: false }) + .click(function(){ + self.popout(); + }) + ); + + this.canvas = document.createElement("canvas"); + this.canvas.width = 500; + this.canvas.height = 500; + this.context = this.canvas.getContext('2d'); + this.showCanvas(); + }, + scale: function(){ + // canvas is shown at this scaling factor + // useful for absolute positioning other elements over the canvas + return this.$(".canvas").width() / this.canvas.width; + }, + outputs: { + image: { + type: "image" + } + }, + showCanvas: function(){ + $(this.canvas).attr({ + "class": "canvas", + "id": "canvas-"+this.model.id, + "style": "max-width:100%" + }); + this.$el.prepend(this.canvas); + }, + _smoothing: true, + inputsmoothing: function (s) { + this._smoothing = s; + // HACK browser-specific stuff + this.context.webkitImageSmoothingEnabled = s; + this.context.mozImageSmoothingEnabled = s; + }, + popout: function() { + if (this.w) { + // Toggle + this.popin(); + return false; + } + + // Cache local canvas + this.localCanvas = this.canvas; + this.localContext = this.context; + $(this.localCanvas).hide(); + + // Open new window to about:blank + this.w = window.open("", "meemooRemoteWindow", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no"); + var self = this; + this.w.addEventListener("unload", function(){ + self.popin(); + }); + + // Popin other + if (Iframework.popoutModule && Iframework.popoutModule !== this) { + Iframework.popoutModule.popin(); + } + Iframework.popoutModule = this; + // TODO: fade out other canvas? + this.w.document.body.innerHTML = ""; + + // Make new canvas + this.canvas = this.w.document.createElement("canvas"); + this.canvas.width = this.localCanvas.width; + this.canvas.height = this.localCanvas.height; + this.context = this.canvas.getContext('2d'); + this.w.document.body.appendChild(this.canvas); + + // Full-screen styling + this.w.document.body.style.backgroundColor="black"; + this.w.document.body.style.margin="0px"; + this.w.document.body.style.padding="0px"; + this.canvas.style.position="absolute"; + this.canvas.style.top="0px"; + this.canvas.style.left="0px"; + this.canvas.style.width="100%"; + this.canvas.style.height="100%"; + + // Smoothing on new canvas + this.inputsmoothing(this._smoothing); + + return false; + }, + popin: function() { + if (this.w) { + this.w = null; + } + this.canvas = this.localCanvas; + this.context = this.localContext; + $(this.canvas).show(); + + // Smoothing on canvas (only matters if it changed while out) + this.inputsmoothing(this._smoothing); + + return false; + } + // showResizer: function(translateX, translateY, scale, rotate){ + // if (!this.resizer) { + // this.resizer = $('
    '); + // this.$el.append(this.resizer); + // } + // var sizedScale = this.scale(); + // this.resizer + // .css({ + // position: "absolute", + // border: "1px solid black", + // top: translateX * sizedScale, + // left: translateY * sizedScale, + // width: 20, + // height: 20 + // }); + // // .hide(); + // var self = this; + // // $(this.canvas) + // // .mouseover(function(){ + // // self.resizer.show(); + // // }) + // // .mouseout(function(){ + // // self.resizer.hide(); + // // }); + // if (translateX || translateY) { + // this.resizer.draggable({}); + // } + // if (scale) { + // this.resizer.resizable({}); + // } + // } + // togglePreview: function(e){ + // if (e.target.checked) { + // this.$el.prepend(this.canvas); + // } else { + // this.$("canvas").remove(); + // } + // } + + }); + + +});