From 0b5cf1a5f48af415d97e5aa5fea36586c17a7927 Mon Sep 17 00:00:00 2001 From: Rick Companje Date: Tue, 29 Oct 2013 23:26:09 +0100 Subject: [PATCH] added working prev/next/save functionality --- Gruntfile.js | 3 +- js_src/buttonbehaviors.js | 35 +++++---- js_src/canvasDrawing.js | 153 ++++++++++++++++++++++++++++++++++++- js_src/sketches.js | 156 ++++++++++++++++++++++++++++++++++++++ www/index.html | 3 +- 5 files changed, 331 insertions(+), 19 deletions(-) create mode 100644 js_src/sketches.js diff --git a/Gruntfile.js b/Gruntfile.js index c6b34bb..05b2e5c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -32,7 +32,8 @@ module.exports = function(grunt) { 'js_src/utils.js', 'js_src/sidebar.js', 'js_src/Message.js', - 'js_src/main.js' + 'js_src/main.js', + 'js_src/sketches.js' ], dest: 'www/js/<%= pkg.name %>.js' } diff --git a/js_src/buttonbehaviors.js b/js_src/buttonbehaviors.js index 797bf64..a2e189b 100644 --- a/js_src/buttonbehaviors.js +++ b/js_src/buttonbehaviors.js @@ -45,6 +45,10 @@ function initButtonBehavior() { btnNew.on('touchstart mousedown', clearDoodle); btnPrint.on('touchstart mousedown', print); + getSavedSketchStatus(); + setSketchModified(false); + //updatePrevNextButtonStateOnClear(); + // btnClear.click(function(e) { // e.preventDefault(); // // console.log("clear"); @@ -191,13 +195,13 @@ function stopPrint() { } -function prevDoodle(e) { - console.log("f:prevDoodle()"); - console.log("f:prevDoodle()"); -} -function nextDoodle(e) { - console.log("f:nextDoodle()"); -} +// function prevDoodle(e) { +// console.log("f:prevDoodle()"); +// console.log("f:prevDoodle()"); +// } +// function nextDoodle(e) { +// console.log("f:nextDoodle()"); +// } function print(e) { console.log("f:print() >> sendPrintCommands = " + sendPrintCommands); @@ -285,6 +289,8 @@ function previewUp(redrawLess) { if (numLayers < maxNumLayers) { numLayers++; } + setSketchModified(true); + // redrawPreview(redrawLess); redrawRenderedPreview(redrawLess); } @@ -293,6 +299,7 @@ function previewDown(redrawLess) { if (numLayers > minNumLayers) { numLayers--; } + setSketchModified(true); // redrawPreview(redrawLess); redrawRenderedPreview(redrawLess); } @@ -302,12 +309,14 @@ function previewTwistLeft(redrawLess) { if (rStep > -previewRotationLimit) rStep -= twistIncrement; // redrawPreview(redrawLess); redrawRenderedPreview(redrawLess); + setSketchModified(true); } function previewTwistRight(redrawLess) { // console.log("f:previewTwistRight()"); if (rStep < previewRotationLimit) rStep += twistIncrement; // redrawPreview(redrawLess); redrawRenderedPreview(redrawLess); + setSketchModified(true); } @@ -390,20 +399,14 @@ function setState(newState,newHasControl) { /* save, next and prev buttons */ switch(newState) { - /*case Printer.WIFIBOX_DISCONNECTED_STATE: + case Printer.WIFIBOX_DISCONNECTED_STATE: disableButton(btnPrevious); disableButton(btnNext); disableButton(btnSave); break; default: - enableButton(btnPrevious, null); - enableButton(btnNext, null); - enableButton(btnSave, null); - break;*/ - default: - disableButton(btnPrevious); - disableButton(btnNext); - disableButton(btnSave); + updatePrevNextButtonState(); + if (isModified) enableButton(btnSave, saveSketch); break; } diff --git a/js_src/canvasDrawing.js b/js_src/canvasDrawing.js index 9aceffc..c412f9a 100644 --- a/js_src/canvasDrawing.js +++ b/js_src/canvasDrawing.js @@ -29,6 +29,8 @@ var movementCounter = 0; var drawVariableLineWeight = false; // set to true to have the momentum of the mouse/touch movement result in larger/smaller strokes var lineweight = 2; +var isModified = false; + /* * * * * * * * * * * * INIT @@ -146,6 +148,8 @@ function draw(_x, _y, _width) { function clearDoodle() { console.log("f:clearDoodle"); + updatePrevNextButtonStateOnClear(); + _points = []; prevX = 0; @@ -162,6 +166,8 @@ function clearDoodle() { clearMainView(); resetPreview(); resetVerticalShapes(); + + setSketchModified(false); } function redrawDoodle(recalcBoundsAndTransforms) { @@ -258,6 +264,8 @@ function adjustPreviewTransformation() { * * * * * * * * * * */ function onCanvasMouseDown(e) { + setSketchModified(true); + // console.log("f:onCanvasMouseDown()"); // console.log("onCanvasMouseDown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY); // console.log("onCanvasMouseDown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY); @@ -285,8 +293,12 @@ function onCanvasMouseDown(e) { var prevPoint = {x:-1, y:-1}; function onCanvasMouseMove(e) { + // console.log("f:onCanvasMouseMove()"); if (!dragging) return; + + setSketchModified(true); + // console.log("onmousemove"); var x, y; @@ -360,6 +372,8 @@ function onCanvasMouseUp(e) { } function onCanvasTouchDown(e) { + setSketchModified(true); + e.preventDefault(); console.log("f:onCanvasTouchDown >> e: " , e); // var x = e.touches[0].pageX - e.touches[0].target.offsetLeft; @@ -382,6 +396,8 @@ function onCanvasTouchDown(e) { } function onCanvasTouchMove(e) { + setSketchModified(true); + e.preventDefault(); // var x = e.touches[0].pageX - e.touches[0].target.offsetLeft; // var y = e.touches[0].pageY - e.touches[0].target.offsetTop; @@ -458,4 +474,139 @@ function onCanvasTouchEnd(e) { function prevent(e) { e.preventDefault(); -} \ No newline at end of file +} + + +//SVG validator: http://validator.w3.org/ +//SVG viewer: http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html +function saveToSvg() { + var lastX = 0, lastY = 0, lastIsMove; + var svg = ''; + + var boundsWidth = doodleBounds[2] - doodleBounds[0]; + var boundsHeight = doodleBounds[3] - doodleBounds[1]; + + svg += '\n'; + svg += '\n'; + svg += '\n'; + svg += '\tDoodle 3D sketch\n'; + + var data = ''; + for (var i = 0; i < _points.length; ++i) { + var x = _points[i][0], y = _points[i][1], isMove = _points[i][2]; + var dx = x - lastX, dy = y - lastY; + + if (i == 0) + data += 'M'; //emit absolute move on first pair of coordinates + else if (isMove != lastIsMove) + data += isMove ? 'm' : 'l'; + + data += dx + ',' + dy + ' '; + + lastX = x; + lastY = y; + lastIsMove = isMove; + } + + svg += '\t\n'; + + var fields = JSON.stringify({'height': numLayers, 'outlineShape': VERTICALSHAPE, 'twist': rStep}); + svg += '\t\n'; + + svg += '\n'; + + return svg; +} + + +//TODO: use local variables instead of _points,numLayers,VERTICALSHAPE and rStep so we can leave a current doodle in tact if an error occurs while parsing +function loadFromSvg(svgData) { + var mode = '', x = 0, y = 0; + + console.log("loading " + svgData.length + " bytes of data..."); + + clearDoodle(); + + var p = svgData.indexOf("-->", p); + if (endP == -1) { console.log("loadFromSvg: could not find metadata end-marker"); return false; } + var metaFields = JSON.parse(svgData.substr(p, endP - p)); + //TODO: log error and return false if parsing failed + for (var k in metaFields) { + var v = metaFields[k]; + switch (k) { + case "height": numLayers = v; break; + case "outlineShape": VERTICALSHAPE = v; break; + case "twist": rStep = v; break; + } + } + + renderToImageDataPreview(); + + return true; +} + diff --git a/js_src/sketches.js b/js_src/sketches.js new file mode 100644 index 0000000..aecc9c5 --- /dev/null +++ b/js_src/sketches.js @@ -0,0 +1,156 @@ +var currentSketchId = 0; +var numSavedSketches = 0; + +function getSavedSketchStatus() { + $.ajax({ + url: wifiboxURL + "/sketch/status", + dataType: 'json', + type: 'GET', + //timeout: this.timeoutTime, + success: function(response) { + if (response.status == 'error' || response.status == 'fail') { + console.log("getSavedSketchStatus fail/error: " + response.msg + " -- ", response); + } else { + console.log("getSavedSketchStatus success: num. saved: " + response.data.number_of_sketches + ", space available: " + response.data.available); + numSavedSketches = response.data.number_of_sketches; + updatePrevNextButtonStateOnClear(); + } + } + }).fail(function() { + console.log("getSavedSketchStatus failed: ", response); + }); +} + +function setSketchModified(_isModified, doNotClearCurrent) { + isModified = _isModified; + + // alert("isModified: " + isModified); + //console.log("setModified: " + isModified + (typeof(doNotClearCurrent) !== 'undefined' ? " (doNotClearCurrent: "+doNotClearCurrent+")" : "")); //TEMP + + if (isModified) enableButton(btnSave, saveSketch); + else disableButton(btnSave); + + //if (typeof(doNotClearCurrent) !== 'undefined' && !doNotClearCurrent) setCurrentSketchId(-1); + + + //sketchModified = isModified; /// ERROR? +} + +function setCurrentSketchId(sId) { + console.log("setCurrentSketchId: " + sId + " / " + numSavedSketches); + // var enablePrev = false; + // var enableNext = false; + + currentSketchId = sId; + + //clamp + if (currentSketchId > numSavedSketches) currentSketchId = numSavedSketches; + if (currentSketchId < 1) currentSketchId = 1; + + //update textbox + //$("#txtSketch").val(currentSketchId); + + updatePrevNextButtonState(); +} + +function updatePrevNextButtonStateOnClear() { + enableButton(btnPrevious, prevDoodle); + disableButton(btnNext); + currentSketchId = numSavedSketches+1; //after the end of the list + disableButton(btnSave); +} + +function updatePrevNextButtonState() { + + //btnPrevious state + if (numSavedSketches==0 || currentSketchId < 2) { + disableButton(btnPrevious); + } else { + enableButton(btnPrevious, prevDoodle); + } + + //btnNext state + if (numSavedSketches==0 || currentSketchId >= numSavedSketches) { + disableButton(btnNext); + } else { + enableButton(btnNext, nextDoodle); + } +} + +function loadSketch(sketchId) { + + $.ajax({ + url: wifiboxURL + "/sketch/" + sketchId, + dataType: 'json', + type: 'GET', +// timeout: this.timeoutTime, + success: function(response) { + if (response.status == 'error' || response.status == 'fail') { + console.log("loadSketch fail/error: " + response.msg + " -- ", response); + } else { + console.log("loadSketch success: loaded id #" + response.data.id, response); + //console.log("sketch content:\n" + response.data.data); + if (loadFromSvg(response.data.data)) { + setSketchModified(false, true); + setCurrentSketchId(response.data.id); + } + } + } + }).fail(function() { + console.log("loadSketch failed: ", response); + }); +} + +//btnSave.mouseup(saveSketch); +function saveSketch() { + svg = saveToSvg(); + console.log("generated SVG [" + _points.length + " points, " + svg.length + " bytes]:\n" + svg); + + $.ajax({ + url: wifiboxURL + "/sketch", + dataType: 'json', + type: 'POST', + data: { data: svg }, + //timeout: this.timeoutTime, + success: function(response) { + if (response.status == 'error' || response.status == 'fail') { + console.log("saveSketch fail/error: " + response.msg + " -- ", response); + } else { + console.log("saveSketch success: saved with id #" + response.data.id, response); + setSketchModified(false, true); + numSavedSketches = response.data.id; + setCurrentSketchId(response.data.id); + } + } + }).fail(function() { + console.log("saveSketch failed: ", response); + }); +} + +function prevDoodle(e) { + console.log("f:prevDoodle(): " + currentSketchId + " / " + numSavedSketches); + //alert('prev ' + numSavedSketches); + //return; + + //TODO: if (enabled) { + var sketchId = (currentSketchId > 0) ? currentSketchId : numSavedSketches; + if (sketchId > 1) sketchId--; + + + //alert(sketchId); + + loadSketch(sketchId); + //} +} + +function nextDoodle(e) { + console.log("f:nextDoodle()"); + //alert('next ' + numSavedSketches); + //return; + + //TODO: if (enabled) { + var sketchId = (currentSketchId > 0) ? currentSketchId : numSavedSketches; + if (sketchId < numSavedSketches) sketchId++; + loadSketch(sketchId); + //} +} diff --git a/www/index.html b/www/index.html index e4367ee..dc1b985 100644 --- a/www/index.html +++ b/www/index.html @@ -31,9 +31,10 @@

-
+
+